1 Business Problem

Sebagai seorang penjual properti, kita ingin membuat model yang mana dapat memprediksi harga properti berdasarkan beberapa informasi yang ada pada data.

Tentukan variabel:

  • target: price
  • prediktor: seluruh variabel terkecuali price

2 Data Wrangling & EDA

1. Read data house_data.csv

house <- read.csv("data_input/house_data.csv")
head(house)

2. Cek struktur data

glimpse(house)
#> Rows: 21,613
#> Columns: 9
#> $ price       <int> 221900, 538000, 180000, 604000, 510000, 1225000, 257500, 2…
#> $ bedrooms    <int> 3, 3, 2, 4, 3, 4, 3, 3, 3, 3, 3, 2, 3, 3, 5, 4, 3, 4, 2, 3…
#> $ bathrooms   <dbl> 1.00, 2.25, 1.00, 3.00, 2.00, 4.50, 2.25, 1.50, 1.00, 2.50…
#> $ sqft_living <int> 1180, 2570, 770, 1960, 1680, 5420, 1715, 1060, 1780, 1890,…
#> $ sqft_lot    <int> 5650, 7242, 10000, 5000, 8080, 101930, 6819, 9711, 7470, 6…
#> $ floors      <dbl> 1.0, 2.0, 1.0, 1.0, 1.0, 1.0, 2.0, 1.0, 1.0, 2.0, 1.0, 1.0…
#> $ waterfront  <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
#> $ grade       <int> 7, 7, 6, 7, 8, 11, 7, 7, 7, 7, 8, 7, 7, 7, 7, 9, 7, 7, 7, …
#> $ yr_built    <int> 1955, 1951, 1933, 1965, 1987, 2001, 1995, 1963, 1960, 2003…
unique(house$waterfront)
#> [1] 0 1
unique(house$grade)
#>  [1]  7  6  8 11  9  5 10 12  4  3 13  1
anyNA(house)
#> [1] FALSE

💡 Hasil pemeriksaan struktur data: - Tipe data pada waterfront perlu diubah menjadi kategorikal, karena hanya memiliki dua data unik dan dapat bersifat dan ordinal. - Semua tipe data selain pada kolom waterfront sudah sesuai. - Tidak terdapat missing value

3. Cleansing Data

house_clean <- house %>% 
  mutate(waterfront = as.factor(waterfront))
head(house_clean)

3. EDA

#persebaran data
boxplot(house_clean$price)

#korelasi
ggcorr(house_clean, label = TRUE)

💡 Insight: - sqft_living dan grade memiliki korelasi > 0.5 yang dapat digunakan untuk model selection based on correlation

3 Modeling

Buatlah 3 model berdasarkan feature selection yg telah dipelajari 1. model all predictor 2. model selection based on correlation (korelasi > 0.5) 3. model selection hasil stepwise (backward/forward/both)

#model all predictor
model_all <- lm(formula = price ~ . ,
                house_clean)
summary(model_all)
#> 
#> Call:
#> lm(formula = price ~ ., data = house_clean)
#> 
#> Residuals:
#>      Min       1Q   Median       3Q      Max 
#> -1384206  -112972   -10077    91060  4251811 
#> 
#> Coefficients:
#>                  Estimate    Std. Error t value             Pr(>|t|)    
#> (Intercept) 6999106.70657  121576.94670  57.569 < 0.0000000000000002 ***
#> bedrooms     -41484.20936    2040.73489 -20.328 < 0.0000000000000002 ***
#> bathrooms     51710.08964    3437.50666  15.043 < 0.0000000000000002 ***
#> sqft_living     177.91392       3.29026  54.073 < 0.0000000000000002 ***
#> sqft_lot         -0.23947       0.03679  -6.509      0.0000000000774 ***
#> floors        17283.13337    3426.85939   5.043      0.0000004609553 ***
#> waterfront1  721804.73094   17406.65326  41.467 < 0.0000000000000002 ***
#> grade        128813.92794    2149.93255  59.915 < 0.0000000000000002 ***
#> yr_built      -3963.73577      64.04988 -61.885 < 0.0000000000000002 ***
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> Residual standard error: 218900 on 21604 degrees of freedom
#> Multiple R-squared:  0.6446, Adjusted R-squared:  0.6445 
#> F-statistic:  4898 on 8 and 21604 DF,  p-value: < 0.00000000000000022
#model corr selection
model_selection <- lm(formula = price ~ sqft_living + grade,
                house_clean)
summary(model_selection)
#> 
#> Call:
#> lm(formula = price ~ sqft_living + grade, data = house_clean)
#> 
#> Residuals:
#>      Min       1Q   Median       3Q      Max 
#> -1065457  -138304   -25043   100447  4794633 
#> 
#> Coefficients:
#>                Estimate  Std. Error t value            Pr(>|t|)    
#> (Intercept) -598108.986   13297.807  -44.98 <0.0000000000000002 ***
#> sqft_living     184.420       2.869   64.29 <0.0000000000000002 ***
#> grade         98554.798    2241.331   43.97 <0.0000000000000002 ***
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> Residual standard error: 250500 on 21610 degrees of freedom
#> Multiple R-squared:  0.5345, Adjusted R-squared:  0.5345 
#> F-statistic: 1.241e+04 on 2 and 21610 DF,  p-value: < 0.00000000000000022
#model stepwise backward
model_stepback <- step(object = model_all,
                       direction = "backward")
#> Start:  AIC=531533.8
#> price ~ bedrooms + bathrooms + sqft_living + sqft_lot + floors + 
#>     waterfront + grade + yr_built
#> 
#>               Df       Sum of Sq              RSS    AIC
#> <none>                           1035294741860252 531534
#> - floors       1   1218939726736 1036513681586988 531557
#> - sqft_lot     1   2030230655068 1037324972515320 531574
#> - bathrooms    1  10844095263314 1046138837123566 531757
#> - bedrooms     1  19802603600782 1055097345461034 531941
#> - waterfront   1  82402185733932 1117696927594184 533187
#> - sqft_living  1 140116227741713 1175410969601965 534275
#> - grade        1 172030644434158 1207325386294410 534854
#> - yr_built     1 183528097123653 1218822838983905 535059
summary(model_stepback)
#> 
#> Call:
#> lm(formula = price ~ bedrooms + bathrooms + sqft_living + sqft_lot + 
#>     floors + waterfront + grade + yr_built, data = house_clean)
#> 
#> Residuals:
#>      Min       1Q   Median       3Q      Max 
#> -1384206  -112972   -10077    91060  4251811 
#> 
#> Coefficients:
#>                  Estimate    Std. Error t value             Pr(>|t|)    
#> (Intercept) 6999106.70657  121576.94670  57.569 < 0.0000000000000002 ***
#> bedrooms     -41484.20936    2040.73489 -20.328 < 0.0000000000000002 ***
#> bathrooms     51710.08964    3437.50666  15.043 < 0.0000000000000002 ***
#> sqft_living     177.91392       3.29026  54.073 < 0.0000000000000002 ***
#> sqft_lot         -0.23947       0.03679  -6.509      0.0000000000774 ***
#> floors        17283.13337    3426.85939   5.043      0.0000004609553 ***
#> waterfront1  721804.73094   17406.65326  41.467 < 0.0000000000000002 ***
#> grade        128813.92794    2149.93255  59.915 < 0.0000000000000002 ***
#> yr_built      -3963.73577      64.04988 -61.885 < 0.0000000000000002 ***
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> Residual standard error: 218900 on 21604 degrees of freedom
#> Multiple R-squared:  0.6446, Adjusted R-squared:  0.6445 
#> F-statistic:  4898 on 8 and 21604 DF,  p-value: < 0.00000000000000022

4 Evaluasi model

Berdasarkan RMSE model regresi manakah yang terbaik?

res <-  data.frame(aktual = house$price,
                   model_all = model_all$fitted.values,
                   model_selection = model_selection$fitted.values,
                   model_stepback = model_stepback$fitted.values)
head(res)
RMSE(y_pred = res$model_all,
     res$aktual)
#> [1] 218864.1
RMSE(y_pred = res$model_selection,
     res$aktual)
#> [1] 250475.5
RMSE(y_pred = res$model_stepback,
     res$aktual)
#> [1] 218864.1

💡 Kesimpulan : Data pada price meliki banyak outlier sehingga digunakan RMSE untuk melihat model terbaik Berdasarkan RMSE model_stepback dan model_all merupakan model terbaik Nilai RMSE model_stepback dan model_all memiliki nilai yang sama karena memiliki prediktor yang sama

5 Interpretasi Model Terbaik:

summary(model_all)
#> 
#> Call:
#> lm(formula = price ~ ., data = house_clean)
#> 
#> Residuals:
#>      Min       1Q   Median       3Q      Max 
#> -1384206  -112972   -10077    91060  4251811 
#> 
#> Coefficients:
#>                  Estimate    Std. Error t value             Pr(>|t|)    
#> (Intercept) 6999106.70657  121576.94670  57.569 < 0.0000000000000002 ***
#> bedrooms     -41484.20936    2040.73489 -20.328 < 0.0000000000000002 ***
#> bathrooms     51710.08964    3437.50666  15.043 < 0.0000000000000002 ***
#> sqft_living     177.91392       3.29026  54.073 < 0.0000000000000002 ***
#> sqft_lot         -0.23947       0.03679  -6.509      0.0000000000774 ***
#> floors        17283.13337    3426.85939   5.043      0.0000004609553 ***
#> waterfront1  721804.73094   17406.65326  41.467 < 0.0000000000000002 ***
#> grade        128813.92794    2149.93255  59.915 < 0.0000000000000002 ***
#> yr_built      -3963.73577      64.04988 -61.885 < 0.0000000000000002 ***
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> Residual standard error: 218900 on 21604 degrees of freedom
#> Multiple R-squared:  0.6446, Adjusted R-squared:  0.6445 
#> F-statistic:  4898 on 8 and 21604 DF,  p-value: < 0.00000000000000022

1. Interpretasi coefficient untuk prediktor kategorik:

  • waterfront = 1, nilai price akan meningkat sebesar 721804.73094 apabila rumah memiliki waterfront

2. Interpretasi coefficient untuk prediktor numerik:

  • intercept = 6999106.70657, menunjukkan nilai proce jika semua variable prediktor = 0
  • bedroom = -41484.20936 , artinya nilai price akan berkurang sebesar 41484.20936 setiap kenaikan satu satuan pada variable ini jika nilai variabel lainnya tetap
  • bathroom = 51710.08964, artinya nilai price akan bertambah sebesar 51710.08964 setiap kenaikan satu satuan pada variable ini jika nilai variabel lainnya tetap
  • sqft_living = 177.91392, artinya nilai price akan bertambah sebesar 177.91392 setiap kenaikan satu satuan pada variable ini jika nilai variabel lainnya tetap
  • sqft_lot = -0.23947, artinya nilai price akan bertambah sebesar 0.23947 jika setiap kenaikan satu satuan pada variable ini nilai variabel lainnya tetap
  • floors = 17283.13337, artinya nilai price akan bertambah sebesar 17283.13337 setiap kenaikan satu satuan pada variable ini jika nilai variabel lainnya tetap
  • grade = 128813.92794, artinya nilai price akan bertambah sebesar 128813.92794 setiap kenaikan satu satuan pada variable ini jika nilai variabel lainnya tetap
  • yr_built = -3963.73577, artinya nilai price akan berkurang sebesar -3963.73577 setiap kenaikan satu satuan pada variable ini jika nilai variabel lainnya tetap

3. Signifikansi prediktor:

  • variabel prediktor bedrooms, bathroom, sqft_living, floors, grade, yr_built memiliki pengaruh yang signifikan terhadap price

4. Adjusted R Squared:

summary(model_all)$adj.r.squared
#> [1] 0.6444532
  • menunjukkan bahwa model_all dapat menjelaskan price cukup baik sebesar 86.91%