Boris Davidovic
library(readxl)
data <- read_excel('./Apartments.xlsx')
Description:
data$ParkingF <- factor(data$Parking,
levels = c(0,1),
labels = c("No", "Yes"))
data$BalconyF <- factor(data$Balcony,
levels = c(0,1),
labels = c("No", "Yes"))
summary(data$Price)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 1400 1710 1950 2019 2290 2820
t_test <- t.test(data$Price, mu = 1900)
print(t_test)
##
## One Sample t-test
##
## data: data$Price
## t = 2.9022, df = 84, p-value = 0.004731
## alternative hypothesis: true mean is not equal to 1900
## 95 percent confidence interval:
## 1937.443 2100.440
## sample estimates:
## mean of x
## 2018.941
It can be concluded that we can reject the null hypothesis of the average price being equal to 1900 EUR as the p-value of the t-test is less than alpha (0.05)
fit1 <- lm(Price ~ Age, data = data)
summary(fit1)
##
## Call:
## lm(formula = Price ~ Age, data = data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -623.9 -278.0 -69.8 243.5 776.1
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2185.455 87.043 25.108 <2e-16 ***
## Age -8.975 4.164 -2.156 0.034 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 369.9 on 83 degrees of freedom
## Multiple R-squared: 0.05302, Adjusted R-squared: 0.04161
## F-statistic: 4.647 on 1 and 83 DF, p-value: 0.03401
cor_coef <- sqrt(summary(fit1)$r.squared)
cor_coef
## [1] 0.230255
The regression coefficient is -8.975 – this means that for every year increase in the age of the apartment, the price per m2 of the apartment decrease by 8.975.
The coefficient of correlation is 0.230255 which indicates that there is some strength in the linear relationship between age and price.
The coefficient of determination is 0.05302 which indicates age has a very small effect on the variability of the apartment price.
library(car)
## Loading required package: carData
scatterplotMatrix((data[,c(1,2,3)]), smooth = FALSE)
The scatter plot matrix indicates that age and distance could have
multicolinearity as their linear relationship forms a horizontal line
which is an indicator of multicolinearity.
fit2 <- lm(Price ~ Age + Distance, data = data)
summary(fit2)
##
## Call:
## lm(formula = Price ~ Age + Distance, data = data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -603.23 -219.94 -85.68 211.31 689.58
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2460.101 76.632 32.10 < 2e-16 ***
## Age -7.934 3.225 -2.46 0.016 *
## Distance -20.667 2.748 -7.52 6.18e-11 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 286.3 on 82 degrees of freedom
## Multiple R-squared: 0.4396, Adjusted R-squared: 0.4259
## F-statistic: 32.16 on 2 and 82 DF, p-value: 4.896e-11
The regression function is: Price = 2460.101 - 7.934(Age) - 20.667(Distance)
vif(fit2)
## Age Distance
## 1.001845 1.001845
mean(vif(fit2))
## [1] 1.001845
As the VIF statistics are highly close to 1, this means there is no multicolinearity.
data$StdResid <- round(rstandard(fit2), 3)
data$CooksD <- round(cooks.distance(fit2), 3)
hist(data$StdResid,
xlab = "Standard Residuals",
ylab = "Frequency",
main = "Histogram of standardized residuals")
hist(data$CooksD,
xlab = "Cooks distance",
ylab = "Frequency",
main = "Histogram of Cooks distance")
head(data[order(data$StdResid),], 3)
## # A tibble: 3 × 9
## Age Distance Price Parking Balcony ParkingF BalconyF StdResid CooksD
## <dbl> <dbl> <dbl> <dbl> <dbl> <fct> <fct> <dbl> <dbl>
## 1 7 2 1760 0 1 No Yes -2.15 0.066
## 2 12 14 1650 0 1 No Yes -1.50 0.013
## 3 12 14 1650 0 0 No No -1.50 0.013
head(data[order(-data$CooksD),], 6)
## # A tibble: 6 × 9
## Age Distance Price Parking Balcony ParkingF BalconyF StdResid CooksD
## <dbl> <dbl> <dbl> <dbl> <dbl> <fct> <fct> <dbl> <dbl>
## 1 5 45 2180 1 1 Yes Yes 2.58 0.32
## 2 43 37 1740 0 0 No No 1.44 0.104
## 3 2 11 2790 1 0 Yes No 2.05 0.069
## 4 7 2 1760 0 1 No Yes -2.15 0.066
## 5 37 3 2540 1 1 Yes Yes 1.58 0.061
## 6 40 2 2400 0 1 No Yes 1.09 0.038
library(dplyr)
##
## Attaching package: 'dplyr'
## The following object is masked from 'package:car':
##
## recode
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
data <- data %>% filter(!StdResid <= -1.499)
data <- data %>% filter(!CooksD >= 0.038)
print(data)
## # A tibble: 77 × 9
## Age Distance Price Parking Balcony ParkingF BalconyF StdResid CooksD
## <dbl> <dbl> <dbl> <dbl> <dbl> <fct> <fct> <dbl> <dbl>
## 1 7 28 1640 0 1 No Yes -0.665 0.007
## 2 18 1 2800 1 0 Yes No 1.78 0.03
## 3 7 28 1660 0 0 No No -0.594 0.006
## 4 28 29 1850 0 1 No Yes 0.754 0.008
## 5 18 18 1640 1 1 Yes Yes -1.07 0.005
## 6 28 12 1770 0 1 No Yes -0.778 0.005
## 7 14 20 1850 0 1 No Yes -0.302 0.001
## 8 18 6 1970 1 1 Yes Yes -0.787 0.004
## 9 22 7 2270 1 0 Yes No 0.455 0.001
## 10 25 2 2570 1 0 Yes No 1.24 0.017
## # ℹ 67 more rows
fit2 <- lm(Price ~ Age + Distance, data = data)
data$StdResid <- round(rstandard(fit2), 3)
data$CooksD <- round(cooks.distance(fit2), 3)
hist(data$StdResid,
xlab = "Standard Residuals",
ylab = "Frequency",
main = "Histogram of standardized residuals")
hist(data$CooksD,
xlab = "Cooks distance",
ylab = "Frequency",
main = "Histogram of Cooks distance")
data$StdFitted <- scale(fit2$fitted.values)
library(car)
scatterplot(y = data$StdResid, x = data$StdFitted,
ylab = "Standard residuals",
xlab = "Standardized fitted values",
boxplots = FALSE,
regLine = FALSE,
smooth = FALSE)
From the scatterplot, there is slight evidence of heteroskedasticity as
there is a small narrowing of the scatter as the fitted values
increase.
hist(data$StdResid,
xlab = "Standard Residuals",
ylab = "Frequency",
main = "Histogram of standardized residuals")
shapiro.test(data$StdResid)
##
## Shapiro-Wilk normality test
##
## data: data$StdResid
## W = 0.92828, p-value = 0.0003172
The standardized residuals are not distributed normally as the p-value from the Shapiro test is signficantly less than 0.05, meaning values are not normally distributed
summary(fit2)
##
## Call:
## lm(formula = Price ~ Age + Distance, data = data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -412.09 -211.38 -54.55 191.65 476.60
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2539.816 74.371 34.15 < 2e-16 ***
## Age -10.715 3.286 -3.26 0.00168 **
## Distance -23.554 2.647 -8.90 2.57e-13 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 250 on 74 degrees of freedom
## Multiple R-squared: 0.561, Adjusted R-squared: 0.5492
## F-statistic: 47.29 on 2 and 74 DF, p-value: 5.885e-14
The intercept coefficient is 2539.816 which is an increase from the previous fit2 summary.
The regression coefficient of Age is -10.715 which means for every year increase in age of the apartment, the price per m2 of the apartment decrease by 10.715. The p-value of Age is 0.00168 which is below 0.05 which indicates Age has a noticeable impact on price.
The regression coefficient of Distance is -23.554 which means for every km increase in distance from the city centre for the apartment, the price per m2 decreases by 23.554. The p-value is 2.57e-13 which is significantly below 0.05, indicating that it has a very strong impact on apartment prices and a much higher impact than age.
The R-square value is 0.561 which is an increase from the previous fit2 regression. This means the removal of excluded units increased how good the fit of the regression is.
The F-squared value in conjunction with the corresponding p-value (5.885e-14 ) indicates the model is statisitically significant.
fit3 <- lm(Price ~ Age + Distance + ParkingF + BalconyF, data = data)
fit3
##
## Call:
## lm(formula = Price ~ Age + Distance + ParkingF + BalconyF, data = data)
##
## Coefficients:
## (Intercept) Age Distance ParkingFYes BalconyFYes
## 2442.301 -10.228 -21.490 119.406 -5.895
The function for apartment price in this model is: Price = 2442.301 - 10.228(Age) - 21.490(Distance) + 119.406(ifParkingYes) - 5.895(ifBalconyYes)
anova(fit2,fit3)
## Analysis of Variance Table
##
## Model 1: Price ~ Age + Distance
## Model 2: Price ~ Age + Distance + ParkingF + BalconyF
## Res.Df RSS Df Sum of Sq F Pr(>F)
## 1 74 4623967
## 2 72 4389016 2 234951 1.9271 0.153
Because the p-value is greater than alpha (0.05), we can’t conclude that fit 3 fits the data better than fit2. To further prove this, from the summary below, we can also see the R-squared is 0.5833 which is slightly higher than fit2, but not enough to justify it fits the data better
summary(fit3)
##
## Call:
## lm(formula = Price ~ Age + Distance + ParkingF + BalconyF, data = data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -378.78 -175.74 -29.07 187.96 491.47
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2442.301 94.196 25.928 < 2e-16 ***
## Age -10.228 3.269 -3.129 0.00253 **
## Distance -21.490 2.817 -7.628 7.58e-11 ***
## ParkingFYes 119.406 61.032 1.956 0.05429 .
## BalconyFYes -5.895 57.343 -0.103 0.91840
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 246.9 on 72 degrees of freedom
## Multiple R-squared: 0.5833, Adjusted R-squared: 0.5602
## F-statistic: 25.2 on 4 and 72 DF, p-value: 4.513e-13
The regression coefficient regarding categorical variables is 119.406 for if there is parking and -5.895 if there is a balcony included with the apartment. This means that the price per m2 of the apartment increases by 119.406 if there is parking and decreases by 5.895 if there is a balcony.
The null hypothesis of the F-statistic is that none of the independent variables have an effect on the dependent variable (i.e. the regression coefficients are 0). Because the p-value of the F-statistic is 4.513e-13 which is less than alpha (0.05), we can reject the null hypothesis and conclude that the dependent variables DO have an effect on the independent variable which is Price.
data$Fitted <- fitted.values(fit3)
data$Residuals <- residuals(fit3)
head(data)
## # A tibble: 6 × 12
## Age Distance Price Parking Balcony ParkingF BalconyF StdResid CooksD StdFitted[,1] Fitted Residuals
## <dbl> <dbl> <dbl> <dbl> <dbl> <fct> <fct> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 7 28 1640 0 1 No Yes -0.682 0.01 -0.740 1763. -123.
## 2 18 1 2800 1 0 Yes No 1.94 0.041 1.12 2356. 444.
## 3 7 28 1660 0 0 No No -0.6 0.008 -0.740 1769. -109.
## 4 28 29 1850 0 1 No Yes 1.20 0.026 -1.63 1527. 323.
## 5 18 18 1640 1 1 Yes Yes -1.14 0.007 -0.318 1985. -345.
## 6 28 12 1770 0 1 No Yes -0.76 0.006 -0.196 1892. -122.
The fitted values for apartment ID2 are 2356.110 and the residuals are 443.8897