Import Data

library('readxl')
d <- read_excel('data.xlsx')
head(d)
## # A tibble: 6 × 19
##   Address  Neighborhood Bedrooms Bathrooms `Square Meters` `Building Age` Garden
##   <chr>    <chr>           <dbl>     <dbl>           <dbl>          <dbl>  <dbl>
## 1 78 Rege… Notting Hill        2         3             179             72      0
## 2 198 Oxf… Westminster         2         1             123             34      1
## 3 18 Rege… Soho                5         3             168             38      0
## 4 39 Picc… Islington           5         1             237             53      1
## 5 116 Fle… Marylebone          4         1             127             23      0
## 6 32 Bond… Notting Hill        5         2              69             69      1
## # ℹ 12 more variables: Garage <dbl>, Floors <dbl>, `Property Type` <chr>,
## #   `Heating Type` <chr>, Balcony <chr>, `Interior Style` <chr>, View <chr>,
## #   Materials <chr>, `Building Status` <chr>, Price <dbl>,
## #   price_for_square_meter <dbl>, Total_Rooms <dbl>
variable.names(d)
##  [1] "Address"                "Neighborhood"           "Bedrooms"              
##  [4] "Bathrooms"              "Square Meters"          "Building Age"          
##  [7] "Garden"                 "Garage"                 "Floors"                
## [10] "Property Type"          "Heating Type"           "Balcony"               
## [13] "Interior Style"         "View"                   "Materials"             
## [16] "Building Status"        "Price"                  "price_for_square_meter"
## [19] "Total_Rooms"
summary(d)
##       Address        Neighborhood     Bedrooms       Bathrooms    
##  Length   :1000   Length   :1000   Min.   :1.000   Min.   :1.000  
##  N.unique : 770   N.unique :  10   1st Qu.:2.000   1st Qu.:1.000  
##  N.blank  :   0   N.blank  :   0   Median :3.000   Median :2.000  
##  Min.nchar:   8   Min.nchar:   4   Mean   :3.013   Mean   :2.003  
##  Max.nchar:  22   Max.nchar:  12   3rd Qu.:4.000   3rd Qu.:3.000  
##                                    Max.   :5.000   Max.   :3.000  
##  Square Meters    Building Age       Garden          Garage     
##  Min.   : 50.0   Min.   : 1.00   Min.   :0.000   Min.   :0.000  
##  1st Qu.: 99.0   1st Qu.:24.00   1st Qu.:0.000   1st Qu.:0.000  
##  Median :148.0   Median :50.00   Median :1.000   Median :1.000  
##  Mean   :149.6   Mean   :49.97   Mean   :0.512   Mean   :0.501  
##  3rd Qu.:201.0   3rd Qu.:76.00   3rd Qu.:1.000   3rd Qu.:1.000  
##  Max.   :249.0   Max.   :99.00   Max.   :1.000   Max.   :1.000  
##      Floors        Property Type     Heating Type       Balcony    
##  Min.   :1.000   Length   :1000   Length   :1000   Length   :1000  
##  1st Qu.:1.000   N.unique :   3   N.unique :   4   N.unique :   3  
##  Median :2.000   N.blank  :   0   N.blank  :   0   N.blank  :   0  
##  Mean   :1.991   Min.nchar:   9   Min.nchar:  11   Min.nchar:  10  
##  3rd Qu.:3.000   Max.nchar:  14   Max.nchar:  18   Max.nchar:  18  
##  Max.   :3.000                                                     
##    Interior Style        View          Materials     Building Status
##  Length   :1000   Length   :1000   Length   :1000   Length   :1000  
##  N.unique :   4   N.unique :   5   N.unique :   4   N.unique :   3  
##  N.blank  :   0   N.blank  :   0   N.blank  :   0   N.blank  :   0  
##  Min.nchar:   6   Min.nchar:   3   Min.nchar:   4   Min.nchar:   3  
##  Max.nchar:  10   Max.nchar:   6   Max.nchar:  17   Max.nchar:   9  
##                                                                     
##      Price         price_for_square_meter  Total_Rooms   
##  Min.   : 386666   Min.   : 6667          Min.   :2.000  
##  1st Qu.:1161400   1st Qu.:10000          1st Qu.:4.000  
##  Median :1721999   Median :12000          Median :5.000  
##  Mean   :1840807   Mean   :12331          Mean   :5.016  
##  3rd Qu.:2390500   3rd Qu.:15000          3rd Qu.:6.000  
##  Max.   :4980000   Max.   :20000          Max.   :8.000

Clean the data

Hanlder duplicate

sum(duplicated(d))
## [1] 0

No duplicated to remove

Handler missing values

colSums(is.na(d))
##                Address           Neighborhood               Bedrooms 
##                      0                      0                      0 
##              Bathrooms          Square Meters           Building Age 
##                      0                      0                      0 
##                 Garden                 Garage                 Floors 
##                      0                      0                      0 
##          Property Type           Heating Type                Balcony 
##                      0                      0                      0 
##         Interior Style                   View              Materials 
##                      0                      0                      0 
##        Building Status                  Price price_for_square_meter 
##                      0                      0                      0 
##            Total_Rooms 
##                      0

No missing values

Convert categorical into factors

d$Neighborhood <- as.factor(d$Neighborhood)
d$`Property Type` <- as.factor(d$`Property Type`)
d$`Heating Type` <- as.factor(d$`Heating Type`)
d$`Interior Style`<- as.factor(d$`Interior Style`)
d$View <- as.factor(d$View)
d$Materials <- as.factor(d$Materials)
d$`Building Status` <-as.factor(d$`Building Status`)
d$Garden <- as.factor(d$Garden)
d$Garage<- as.factor(d$Garage )
d$Balcony <- as.factor(d$Balcony)

Building our mutli linear regretion model

Spliting data

set.seed(2026)
total <- nrow(d)
train <- floor(total * 0.8)
test <- floor(total * 0.2)
train_ids <- sample(1:train, train)
train_data <- d[train_ids,]
test_data <- d[-train_ids,]
print(paste('Total: ', total, ' Train: ', train, ' Test: ', test, ' Train IDs: ', length(train_ids), ' Train Data: ', nrow(train_data), ' Test Data: ', nrow(test_data)))
## [1] "Total:  1000  Train:  800  Test:  200  Train IDs:  800  Train Data:  800  Test Data:  200"
head(train_data)
## # A tibble: 6 × 19
##   Address  Neighborhood Bedrooms Bathrooms `Square Meters` `Building Age` Garden
##   <chr>    <fct>           <dbl>     <dbl>           <dbl>          <dbl> <fct> 
## 1 154 Str… Kensington          4         2              99             22 1     
## 2 22 Park… Greenwich           1         2             152              2 0     
## 3 96 Flee… Soho                5         1             247             60 0     
## 4 52 Rege… Soho                4         2             166             98 1     
## 5 191 Reg… Camden              1         1             228              9 1     
## 6 188 Str… Shoreditch          5         2             167             67 0     
## # ℹ 12 more variables: Garage <fct>, Floors <dbl>, `Property Type` <fct>,
## #   `Heating Type` <fct>, Balcony <fct>, `Interior Style` <fct>, View <fct>,
## #   Materials <fct>, `Building Status` <fct>, Price <dbl>,
## #   price_for_square_meter <dbl>, Total_Rooms <dbl>
head(test_data)
## # A tibble: 6 × 19
##   Address  Neighborhood Bedrooms Bathrooms `Square Meters` `Building Age` Garden
##   <chr>    <fct>           <dbl>     <dbl>           <dbl>          <dbl> <fct> 
## 1 178 Pic… Shoreditch          5         3             249             13 1     
## 2 55 Stra… Camden              3         3             171             34 1     
## 3 176 Fle… Camden              5         1              67             83 0     
## 4 72 Camd… Islington           5         1             121             77 0     
## 5 95 Park… Greenwich           1         2             177             80 1     
## 6 183 Str… Westminster         5         1             109             25 1     
## # ℹ 12 more variables: Garage <fct>, Floors <dbl>, `Property Type` <fct>,
## #   `Heating Type` <fct>, Balcony <fct>, `Interior Style` <fct>, View <fct>,
## #   Materials <fct>, `Building Status` <fct>, Price <dbl>,
## #   price_for_square_meter <dbl>, Total_Rooms <dbl>

Train our Model

model <- lm(Price ~ Neighborhood + Bedrooms + Bathrooms + `Square Meters` + `Building Age` + Garden + Garage + Floors + `Property Type` + `Heating Type` + Balcony + `Interior Style` + View + Materials + `Building Status` + Total_Rooms, data=train_data)

Test our Model

Predict

predicted <- predict(model, test_data)

Calculate the Mean Average Error

mae <- mean(abs(test_data$Price - predicted))
mae
## [1] 164050.4

Calculate Relative error

re <- mae / mean(d$Price)
re
## [1] 0.08911875

Interpretation

I have choosed a housing dataset from kaggle (https://www.kaggle.com/code/atamoaty/houses/notebook) then I used it to predict house price using different variables. I have splitted the data 80% train, then 20% testing, trained the model then made prediction then calculated MAE then calculated the relative error

The Mean Average Error was 164050.4 while the average price was 1840807 which give use relative error of like 8% which is not bad. That mean the model can be able to perform the house predict with 8% possible error which is a reasonable good accuracy


Variable Selection

Variable selection is a process by which we choose which independent variables should be included in a regression model The goal is to keep the variables that help predict the target variable and remove those that add little value

Forward Selection

Starts with no variables and adds them one by one.

model0 <- lm(Price ~ 1, data=d)
model1 <- lm(Price ~ ., data=d)
step(model0, scope=list(lower=model0, upper=model1), direction="forward")

Backward Elimination

Starts with all variables and removes the least useful ones.

full_model <- lm(Price ~ ., data=d)
step(full_model, direction="backward")

Stepwise Selection

Combination of forward and backward

full_model <- lm(Price ~ ., data=d)
step(full_model, direction="both")

Using p-values

Remove variables whose p-value is greater than 0.05

Using Correlation

Remove variables that are highly correlated with each other (multicollinearity). If two variables contain almost the same information, you may keep only one.