INTRODUCTION

Pada kesempatan kali ini penulis ingin membuat sebuah model dengan menggunakan regression model. Adapun data yang digunakan adalah data yang berasal dari https://www.kaggle.com/greenwing1985/housepricing yang berisi data simulasi harga rumah berdasarkan atribut-atribut propertinya. Data terdiri dari 15 variabel prediktor dan 1 target variabel. Adapaun target variabel yang akan digunakan dalam pembuatan model ini adalah Prices.

DATA PREPROCESSING

Tahapan Data Preprocessing antara lain :

  • Load library yang digunakan
  • Load data yang akan digunakan
  • Apakah terdapat kolom yang belum sesuai tipe datanya?
  • Apakah terdapat missing value?

Load Library

# load library
library(tidyverse)
library(GGally) 
library(car)
library(MLmetrics)
library(lmtest)

Load Data

# load data
house <- read.csv("data_input/HousePrices_HalfMil.csv")
head(house)

Cek Tipe Data

# cek tipe data
str(house)
## 'data.frame':    500000 obs. of  16 variables:
##  $ Area         : int  164 84 190 75 148 124 58 249 243 242 ...
##  $ Garage       : int  2 2 2 2 1 3 1 2 1 1 ...
##  $ FirePlace    : int  0 0 4 4 4 3 0 1 0 2 ...
##  $ Baths        : int  2 4 4 4 2 3 2 1 2 4 ...
##  $ White.Marble : int  0 0 1 0 1 0 0 1 0 0 ...
##  $ Black.Marble : int  1 0 0 0 0 1 0 0 0 0 ...
##  $ Indian.Marble: int  0 1 0 1 0 0 1 0 1 1 ...
##  $ Floors       : int  0 1 0 1 1 1 0 1 1 0 ...
##  $ City         : int  3 2 2 1 2 1 3 1 1 2 ...
##  $ Solar        : int  1 0 0 1 1 0 0 0 0 1 ...
##  $ Electric     : int  1 0 0 1 0 0 1 1 0 0 ...
##  $ Fiber        : int  1 0 1 1 0 1 1 0 0 0 ...
##  $ Glass.Doors  : int  1 1 0 1 1 1 1 1 0 0 ...
##  $ Swiming.Pool : int  0 1 0 1 1 1 0 1 1 1 ...
##  $ Garden       : int  0 1 0 1 1 1 1 0 0 0 ...
##  $ Prices       : int  43800 37550 49500 50075 52400 54300 34400 50425 29575 22300 ...

Dari data diatas di dapatkan informasi sebagai berikut :

  • Data terdiri dari 500.000 baris dana 16 kolom
  • Semua variabel prediktor dan target variabel bertipe integer

Data Description : - Area : Luas tanah - Garage : Jumlah garasi (2,1,3) - FirePlace : Jumlah tempat perapian (0,4,3,1,2) - Baths : Jumlah kamar mandi (2,4,3,1,5) - White.Marble : Warna marmer (0,1) - Black.Marble : Warna marmer (1,0) - Indian.Marble: Warna marmer (0,1) - Floors : Jumlah lantai (0,1) - City : Jauh tidaknya dari pusat kota (3,2,1) - Solar : Ada tidaknya tenaga surya (1,0) - Electric : Listrik (1,0) - Fiber : Ada tidaknya fiber (1,0) - Glass.Doors : Tipe pintu kaca (1,0) - Swiming.Pool : Ada tidaknya kolam renang (0,1) - Garden : Ada tidaknya halaman rumah (kebun) (0,1) - Prices : Harga rumah (sebagai target variabel)

Karena tipe data sudah sesuai, maka kita tidak perlu untuk mengubahnya.

house <- house %>% 
  mutate_if(is.integer, as.numeric)
str(house)
## 'data.frame':    500000 obs. of  16 variables:
##  $ Area         : num  164 84 190 75 148 124 58 249 243 242 ...
##  $ Garage       : num  2 2 2 2 1 3 1 2 1 1 ...
##  $ FirePlace    : num  0 0 4 4 4 3 0 1 0 2 ...
##  $ Baths        : num  2 4 4 4 2 3 2 1 2 4 ...
##  $ White.Marble : num  0 0 1 0 1 0 0 1 0 0 ...
##  $ Black.Marble : num  1 0 0 0 0 1 0 0 0 0 ...
##  $ Indian.Marble: num  0 1 0 1 0 0 1 0 1 1 ...
##  $ Floors       : num  0 1 0 1 1 1 0 1 1 0 ...
##  $ City         : num  3 2 2 1 2 1 3 1 1 2 ...
##  $ Solar        : num  1 0 0 1 1 0 0 0 0 1 ...
##  $ Electric     : num  1 0 0 1 0 0 1 1 0 0 ...
##  $ Fiber        : num  1 0 1 1 0 1 1 0 0 0 ...
##  $ Glass.Doors  : num  1 1 0 1 1 1 1 1 0 0 ...
##  $ Swiming.Pool : num  0 1 0 1 1 1 0 1 1 1 ...
##  $ Garden       : num  0 1 0 1 1 1 1 0 0 0 ...
##  $ Prices       : num  43800 37550 49500 50075 52400 ...

Cek Missing Value

colSums(is.na(house))
##          Area        Garage     FirePlace         Baths  White.Marble 
##             0             0             0             0             0 
##  Black.Marble Indian.Marble        Floors          City         Solar 
##             0             0             0             0             0 
##      Electric         Fiber   Glass.Doors  Swiming.Pool        Garden 
##             0             0             0             0             0 
##        Prices 
##             0

Dari data yang ditampilkan diatas, tidak terdapat missing value.

EXPLORATORY DATA ANALYSIS (EDA)

Beberapa hal yang bisa dilakukan dengan melakukan EDA

  • Cek korelasi antar variabel
  • Buat heatmap jika ada variabel kategori
  • Cek distribusi dari beberapa variabel

Cek Korelasi

# Mencari korelasi dari variabel numerik
ggcorr(house, label = TRUE, label_size = 2, hjust = 1, layout.exp = 2)

Dari data yang ditampilkan diatas, dapat disimpulkan sebagai berikut :

  • Variabel prediktor yang bernilai 0 artinya tidak ada korelasi dengan variabel targetnya.
  • Variabel prediktor bernilai > 0.7 atau < -0.7 artinya berkorelasi kuat dengan variabel targetnya.
  • Variabel prediktor bernilai < 0.7 atau > -0.7 artinya berkorelasi lemah dengan variabel targetnya.

Kita hanya akan menggunakan beberapa variabel prediktor yaitu variabel - Glass.Doors - Fiber - City - Floors - Indian.Marble dan - White.Marble

CROSS VALIDATION

Sebelum membuat model regresi linear, terlebih dahulu kita membagi (split) data house menjadi 2 bagian yaitu data_train sebanyak (80%) dan data_test (20%).

set.seed(123) # random secara acak
row_data <- nrow(house)
index <- sample(row_data, row_data*0.8)

data_train <- house[ index, ]
data_test  <- house[ -index, ]

MODELING

Setelah dilakukan cross validation pada tahap sebelumnya, maka langkah selanjutnya adalah kita membuat model dari data_train.

# buat model regresi linear
model_house <- lm(Prices ~ Glass.Doors + Fiber + City + Floors 
                  + Indian.Marble + White.Marble 
                  ,data_train)
summary(model_house)
## 
## Call:
## lm(formula = Prices ~ Glass.Doors + Fiber + City + Floors + Indian.Marble + 
##     White.Marble, data = data_train)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -9367.0 -2152.0    -0.5  2148.0  9354.7 
## 
## Coefficients:
##                Estimate Std. Error t value            Pr(>|t|)    
## (Intercept)   18138.920     16.774  1081.4 <0.0000000000000002 ***
## Glass.Doors    4434.556      9.679   458.2 <0.0000000000000002 ***
## Fiber         11752.405      9.679  1214.3 <0.0000000000000002 ***
## City           3491.729      5.929   589.0 <0.0000000000000002 ***
## Floors        14998.245      9.678  1549.6 <0.0000000000000002 ***
## Indian.Marble -4997.352     11.857  -421.5 <0.0000000000000002 ***
## White.Marble   9024.401     11.857   761.1 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 3061 on 399993 degrees of freedom
## Multiple R-squared:  0.9362, Adjusted R-squared:  0.9362 
## F-statistic: 9.782e+05 on 6 and 399993 DF,  p-value: < 0.00000000000000022

INTERPRETASI

Interpretasi dari summary(), antara lain :

Distribusi Error/Residuals

summary(model_house$residuals)
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## -9367.011 -2151.961    -0.469     0.000  2148.039  9354.742
boxplot(model_house$residuals)

Hasil Uji Signifikansi Slope & Intercept

  • Setiap kenaikan Glass.Doors sebanyak 1 satuan maka akan diikuti kenaikan Prices sebesar 4434.556
  • Setiap kenaikan Fiber sebanyak 1 satuan maka akan diikuti kenaikan Prices sebesar 11752.405
  • Setiap kenaikan City sebanyak 1 satuan maka akan diikuti kenaikan Prices sebesar 3491.729
  • Setiap kenaikan Floors sebanyak 1 satuan maka akan diikuti kenaikan Prices sebesar 14998.245
  • Setiap kenaikan Indian.Marble sebanyak 1 satuan maka akan diikuti penurunan Prices sebesar 4997.352
  • Setiap kenaikan White.Marble sebanyak 1 satuan maka akan diikuti kenaikan Prices sebesar 9024.401

Adjusted R-Squared & p-value

  • Nilai Adjusted R-squared = 0.9362, artinya variabel prediktor yang digunakan dalam membuat model_house berhubungan signifikan terhadap variabel target Prices sebesar 93,62%, dan sisanya sebesar 6,38% dijelaskan oleh faktor lain.

  • Nilai p-value < 0.05 artinya variabel prediktor yang digunakan dalam membuat model_house berhubungan signifikan terhadap variabel target Prices.

PREDICT

Kita ingin memprediksi performa model di data train.

pred_train <- predict(model_house, data_train)

data.frame(MAE = MAE(pred_train, data_train$Prices),
           MAPE = MAPE(pred_train, data_train$Prices),
           RMSE = RMSE(pred_train, data_train$Prices)
           )

Selanjutnya kita juga ingin memprediksi performa model di data test.

pred_test <- predict(model_house, data_test)

data.frame(MAE = MAE(pred_test, data_test$Prices),
           MAPE = MAPE(pred_test, data_test$Prices),
           RMSE = RMSE(pred_test, data_test$Prices)
           )

NOTE Bisa kita perhatikan bahwa pada data train dan data test performanya mirip atau tidak berbeda jauh. Maka kita dapat simpulkan bahwa model tidak mengalami overfit maupun underfit.

summary(model_house)
## 
## Call:
## lm(formula = Prices ~ Glass.Doors + Fiber + City + Floors + Indian.Marble + 
##     White.Marble, data = data_train)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -9367.0 -2152.0    -0.5  2148.0  9354.7 
## 
## Coefficients:
##                Estimate Std. Error t value            Pr(>|t|)    
## (Intercept)   18138.920     16.774  1081.4 <0.0000000000000002 ***
## Glass.Doors    4434.556      9.679   458.2 <0.0000000000000002 ***
## Fiber         11752.405      9.679  1214.3 <0.0000000000000002 ***
## City           3491.729      5.929   589.0 <0.0000000000000002 ***
## Floors        14998.245      9.678  1549.6 <0.0000000000000002 ***
## Indian.Marble -4997.352     11.857  -421.5 <0.0000000000000002 ***
## White.Marble   9024.401     11.857   761.1 <0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 3061 on 399993 degrees of freedom
## Multiple R-squared:  0.9362, Adjusted R-squared:  0.9362 
## F-statistic: 9.782e+05 on 6 and 399993 DF,  p-value: < 0.00000000000000022

CEK ASUMSI

Karena kita ingin melakukan prediksi dan interpretasi, maka perlu dilakukan cek asumsi.

Linearity

Model regresi linearnya adalah :

\[ Prices = 18138.920 + 4434.556\times Glass.Doors + 11752.405\times Fiber + 3491.729\times City \\ + 14998.245\times Floors -4997.352\times Indian.Marble + 9024.401\times White.Marble \]

ggcorr(house, label = TRUE, label_size = 2, hjust = 1, layout.exp = 2)

Normality

Residual atau error dari data perlu berdistribusi normal.

hist(model_house$residuals)

plot(density(model_house$residuals))

Dari data (grafik) yang ditampilkan diatas bahwa residual atau error dari data berdistribusi normal (Model berasumsi bahwa error ini memiliki distribusi normal yang berpusat di angka 0).

qqPlot(model_house$residuals)

## 373032 210488 
## 293278   8652

Homocesdasticity

bptest(model_house)
## 
##  studentized Breusch-Pagan test
## 
## data:  model_house
## BP = 8.7898, df = 6, p-value = 0.1858

Nilai p-value > 0.05: Artinya error(residual) bersifat konstan (Homocesdasticity).

Multicolinearity

vif(model_house)
##   Glass.Doors         Fiber          City        Floors Indian.Marble 
##      1.000010      1.000013      1.000012      1.000002      1.334860 
##  White.Marble 
##      1.334860

Nilai VIF di setiap prediktor < 10 artinya tidak terjadi Multikolinearitas.

CONCLUSION

  • Variabel prediktor yang berguna untuk menggambarkan variasi dari harga rumah (Prices) adalah : Glass.Doors, Fiber, City, Floors, Indian.Marble dan White.Marble.

  • Model akhir yang telah kita buat mendapatkan nilai R Squared = 0,9362, artinya variabel prediktor yang digunakan dalam membuat model_house berhubungan signifikan terhadap variabel target Prices sebesar 93,62%, dan sisanya sebesar 6,38% dijelaskan oleh faktor lain.

  • Nilai R-Squared juga bisa diartikan bahwa variabel prediktor dapat menjelaskan sebesar 93,62% dari variasi harga rumah.

  • Nilai RMSE di data-train = 3060.576 sedangkan RMSE di data_test = 3062.738, artinya performanya mirip atau tidak berbeda jauh. Maka kita dapat simpulkan bahwa model tidak mengalami overfit maupun underfit.