Price Point Perspectives: Analyzing the Impact of Certain Housing Features on its Sale Prices

Introduction

- Housing attributes are influential on price and demand
- Help potential buyers, sellers, and investors 
- This data set covers several attributes like bedroom count, net square meters, center distance, metro distance, floor number, age

Problem Statement

- Understanding how various housing attributes interact with pricing dynamics can shed light on disparities in access to housing.
- We aim to address the issue of housing affordability by examining how different factors influence pricing, ultimately helping customers make informed decisions within their budgetary constraints.

Project Objective

Our objectve is to determine how certain housing features have an impact on the overall sale price of a house. 

Method - Multiple Linear Regression

Step 1: Install and load required libraries

#install.packages("ggplot2")
#install.packages("gclus")
#install.packages("ggpubr")
#install.packages("tidyverse")
library(ggplot2) #Used for visualization
library(gclus) #allows us to create a scatterplot
## Loading required package: cluster
library(ggpubr) #Helps us create results that are publication ready
library(tidyverse) #For data manipulation and visualization
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ lubridate 1.9.3     ✔ tibble    3.2.1
## ✔ purrr     1.0.2     ✔ tidyr     1.3.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(readxl) #Helps us to read the excel file
theme_set(theme_pubr()) #gives a clear plot that we can use 

Step 2: Import the data

housing_data <- read_excel("/Users/allysonguan/Downloads/house.xlsx")

Step 3: Descriptive Statistics

summary(housing_data)
##  bedroom_count       net_sqm       center_distance  metro_distance   
##  Min.   : 1.000   Min.   : 10.24   Min.   :  11.8   Min.   :  1.245  
##  1st Qu.: 2.000   1st Qu.: 52.24   1st Qu.: 635.9   1st Qu.: 56.157  
##  Median : 3.000   Median : 91.83   Median :1143.1   Median :101.388  
##  Mean   : 3.733   Mean   :118.94   Mean   :1090.5   Mean   :105.665  
##  3rd Qu.: 5.000   3rd Qu.:150.99   3rd Qu.:1554.3   3rd Qu.:148.481  
##  Max.   :17.000   Max.   :750.97   Max.   :1999.8   Max.   :330.275  
##      floor         age_of_house       price       
##  Min.   : 1.000   Min.   : 0.00   Min.   : 86114  
##  1st Qu.: 2.000   1st Qu.:25.00   1st Qu.: 92934  
##  Median : 8.000   Median :48.00   Median : 95338  
##  Mean   : 9.397   Mean   :48.58   Mean   : 95701  
##  3rd Qu.:16.000   3rd Qu.:72.00   3rd Qu.: 97981  
##  Max.   :24.000   Max.   :97.00   Max.   :118135
Define Variables-
Independent variables: bedroom count, net sq. meters, center distance (km), metro distance (km), floor, age of house (years)
Dependent variable: Price ($)

Step 4: Data Visualization

#Scatterplot Matrix 
pairs( ~ bedroom_count + net_sqm + center_distance + metro_distance + floor + age_of_house + price, data = housing_data)

Step 5: Create the Estimated Regression Model

model <- lm(price ~ bedroom_count + net_sqm + center_distance + metro_distance + floor + age_of_house, data = housing_data)
summary(model)
## 
## Call:
## lm(formula = price ~ bedroom_count + net_sqm + center_distance + 
##     metro_distance + floor + age_of_house, data = housing_data)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -15781.7  -1120.4     56.3   1205.5  13785.8 
## 
## Coefficients:
##                   Estimate Std. Error t value Pr(>|t|)    
## (Intercept)      9.460e+04  1.300e+02  727.77   <2e-16 ***
## bedroom_count    3.086e+02  2.102e+01   14.68   <2e-16 ***
## net_sqm          2.520e+01  5.049e-01   49.91   <2e-16 ***
## center_distance -3.361e+00  7.015e-02  -47.91   <2e-16 ***
## metro_distance   6.998e+00  6.415e-01   10.91   <2e-16 ***
## floor            1.217e+02  4.989e+00   24.39   <2e-16 ***
## age_of_house    -2.613e+01  1.149e+00  -22.74   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2079 on 4301 degrees of freedom
## Multiple R-squared:  0.7191, Adjusted R-squared:  0.7187 
## F-statistic:  1835 on 6 and 4301 DF,  p-value: < 2.2e-16
Estimated Regression Model: ŷ = 94603.76 + 308.57*bedroom + 25.20*net_sqm - 3.36*center_distance + 7.0*metro_distance + 121.66*floor - 26.13*age_of_house
 
Coefficient Interpretation: 
b0- The starting value, “baseline” 
b1- Each additional bedroom would increase the price by $308.57
b2- Price increases by $25.20 for each additional square meter
b3- For each additional kilometer from the city center, the price decreases by $3.36 
b4- For each additional kilometer from the metro, the price would increase by $7
b5- Each level up, results in an increase by $121.66
b6- For each additional year the house increases in age, the price would decrease by $26.13

Model Interpretation: 
- Adj R-squared is average
- Model is significant (p-value < 0.05)
- All the independent variables are significant (p-value < 0.05)

Step 6: Calculate the Correlation Matrix

corr <- cor(housing_data)
rounded_correlations <- round(corr, 2) #Round results to two decimal places
print(rounded_correlations)
##                 bedroom_count net_sqm center_distance metro_distance floor
## bedroom_count            1.00    0.75           -0.01           0.02 -0.53
## net_sqm                  0.75    1.00           -0.01           0.03 -0.41
## center_distance         -0.01   -0.01            1.00           0.58  0.02
## metro_distance           0.02    0.03            0.58           1.00  0.00
## floor                   -0.53   -0.41            0.02           0.00  1.00
## age_of_house            -0.06   -0.05            0.01           0.01  0.02
## price                    0.55    0.68           -0.42          -0.15 -0.14
##                 age_of_house price
## bedroom_count          -0.06  0.55
## net_sqm                -0.05  0.68
## center_distance         0.01 -0.42
## metro_distance          0.01 -0.15
## floor                   0.02 -0.14
## age_of_house            1.00 -0.23
## price                  -0.23  1.00
Interpretation: 
bedroom_count (0.55): A moderatly strong correlation, having more bedrooms mean a higer price
net_sqm (0.68): A strong correlation meaning that larger house would sell within a higher rate (net_sqm vs price)
center_distance (-0.42): A moderatly negative correlation showing that houses that are further from the city center tend to cost a bit less
metro_distance (-0.15): A weak negative correlation indicating that proximity to a metro station has only a slight effect on increasing house prices.
floor (-0.14): A weak correlation implying properties on higher floors do not correlate with higher prices
age_of_house (-0.23): A moderatly negative correlation showing older houses might sell less than newer ones, however the relationship isn't very strong

Step 7: Residual analysis

layout(matrix(c(1,2,3,4), 2,2))
plot(model)

Interpretation: 
The clustering of residual points near the red line indicate that the model’s prediction are close to the actual values.

Normal Q-Q Plot mostly aligns with the diagonal line, which would indicate that the residuals are normally distributed. The funnel shape suggests a variability of our errors change with the level of the house prices we predict--more variables when prices increase.

Step 8: Predicting w/ New Information & Prediction Interval

#Predicting price with new information
new_data <- data.frame(bedroom_count = 3, net_sqm = 175, center_distance = 900, metro_distance = 250,
                       floor = 2, age_of_house = 38)
prediction <- predict(model, newdata = new_data)
prediction
##        1 
## 97914.63
Interpretation: Given that a 38 year old home has 3 bed rooms, 175 net sq. meters of interior space, has 2 floors, is 900 km away from the nearest city center, and 250 km away from the nearest metro station, the estimated price of the home would be $97,914.63 
#95% Prediction Interval
prediction_interval <- predict(model, newdata = new_data, interval = "prediction")
prediction_interval
##        fit      lwr      upr
## 1 97914.63 93831.54 101997.7
Interpretation: The "fit" value of $97,914.63 is the predicted sale price of the house based on the multiple linear regression model and the specific values of the housing features for this particular house.
However, due to the variability and uncertainty in the data and the model, there is a 95% probability that the actual sale price of the house will fall within the range of $93,831.54 to $101,997.70.

Conclusion and Recommendations

Conclusion:
- Our results convey that certain variables regarding housing can play a significant role in determining the house price.
- Because our p-value < 0.05, we can conclude that all six variables were statistically significant.
Recommendations:
- This model can be used to monitor whether these factors continue to affect housing prices.
- Accurately price the houses based on the features that they have.
- Real estate agents can use this information to tailor their selling strategies to buyers, depending on what buyers might be looking for.