Prediksi Biaya Asuransi Kesehatan Menggunakan Model Linear Regression
1. Import Library
Berikut merupakan packages yang digunakan pada analisis data insurance
library(dplyr)
library(GGally)
library(stringr)
library(lmtest)
library(car)
library(caret)
library(performance)
library(tidyr)
library(rmdformats)
library(ggplot2)
library(psych)2. Read Data
insurance <- read.csv("data input/insurance.csv", stringsAsFactors = T)
rmarkdown::paged_table(insurance)3. Data Wrangling
glimpse(insurance)#> Rows: 1,338
#> Columns: 7
#> $ age <int> 19, 18, 28, 33, 32, 31, 46, 37, 37, 60, 25, 62, 23, 56, 27, 1…
#> $ sex <fct> female, male, male, male, male, female, female, female, male,…
#> $ bmi <dbl> 27.900, 33.770, 33.000, 22.705, 28.880, 25.740, 33.440, 27.74…
#> $ children <int> 0, 1, 3, 0, 0, 0, 1, 3, 2, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0…
#> $ smoker <fct> yes, no, no, no, no, no, no, no, no, no, no, yes, no, no, yes…
#> $ region <fct> southwest, southeast, southeast, northwest, northwest, southe…
#> $ charges <dbl> 16884.924, 1725.552, 4449.462, 21984.471, 3866.855, 3756.622,…
Description
- age : umur
nasabah
- sex : jenis kelamin nasabah
-
bmi : index massa tubuh
- children :
jumlah tanggungan anak nasabah
- smoker : apakah
nasabah perokok atau tidak
- region : region tempat
tinggal ansabah
- charges : biaya pengobatan (medical
cost) yang ditanggung oleh pihak asuransi terhadap nasabah
Inspeksi data unique
unique(insurance$children)#> [1] 0 1 3 2 5 4
Menghapus data duplikat
insurance <- insurance[!duplicated(insurance),]Inspeksi missing value
is.na(insurance) %>% colSums()#> age sex bmi children smoker region charges
#> 0 0 0 0 0 0 0
Inspeksi range variabel target
range(insurance$charges)#> [1] 1121.874 63770.428
4. Business Problem
Kita ingin memprediksi biaya asuransi charges
berdasarkan seluruh prediktor yang ada di dataset. * variable target
(y): charges * variable prediktor (x): age, sex, bmi, children, smoker,
region
5. Exploratory Data Analysis (EDA)
Mari kita cek persebaran data numerik pada dataset
pairs.panels(insurance[-c(2,5,6)])
Plot di atas menunjukkan visualisasi secara garis besar persebaran data
seluruh variabel numerik pada dataset
insurance. Mari kita
bedah satu per satu sebagai berikut.
hist(insurance$age)range(insurance$age)#> [1] 18 64
💡 Insight:
* Pihak asuransi memiliki nasabah dengan rentang umur
18 - 64 tahun, dan didominasi oleh nasabah yang berumur < 20
tahun
hist(insurance$bmi)range(insurance$bmi)#> [1] 15.96 53.13
💡 Insight:
* Nilai bmi nasabah berada pada rentang 15.96 -
53.13, dimana bmi 25 - 35 adalah yang dominan. Berdasarkan klasifikasi
obesitas, rentang bmi 25 - 35 masuk ke dalam kelas overweight hingga
obesitas level 1
hist(insurance$charges)range(insurance$charges)#> [1] 1121.874 63770.428
💡 Insight:
* Biaya pengobatan yang dikeluarkan oleh pihak
asuransi berada pada rentang 1121.874 - 63770.428, dimana nilai yang
dominan ada di < 15000an
boxplot(insurance$charges, horizontal = T)
💡 Insight:
- Variabel
chargesmemiliki outlier atas (outlier di nilai yang besar) - Persebaran data kita ada di nilai kecil (0-30000an)
Mari kita lihat persebaran data charges nasabah yang
memiliki nilai bmi < 30 dan > 30.
# subset data dengan bmi<30
bmi_less30 <- insurance[insurance$bmi<30,]
hist(bmi_less30$charges)
💡 Insight:
* Persebaran data charges pada nasabah
dengan bmi < 30 cukup stabil
# subset data dengan bmi < 30
bmi_more30 <- insurance[insurance$bmi>30,]
hist(bmi_more30$charges)
💡 Insight:
* Persebaran data charges pada nasabah
dengan bmi > 30 cenderung fluktuatif
# subset data dengan bmi 25-35
bmi_range <- insurance[insurance$bmi>25 & insurance$bmi<35,]
hist(bmi_range$charges)
💡 Insight:
* Persebaran data charges pada nasabah
dengan bmi 25-35 cukup stabil namun sedikit fluktuatif
Mari kita lihat persebaran data smoker terhadap biaya
charges
plot(insurance$smoker, insurance$charges, horizontal=T)
💡 Insight:
* Nasabah perokok memiliki range charges yang lebih
tinggi yaitu 12000-60000an dibandingkan bukan perokok yakni
0-20000an
Mari kita lihat persebaran data age terhadap biaya
charges.
plot(insurance$age, insurance$charges)
💡 Insight:
* Dari hasil plot di atas, diperoleh informasi yang
menarik bahwa bertambahnya umur nasabah, maka nilai charges nya juga
bertambah tinggi.
Mari kita lihat persebaran data sex terhadap biaya
charges.
plot(insurance$sex, insurance$charges, horizontal=T)
💡 Insight:
* Dari plot di atas, diperoleh informasi bahwa pada
dataset kita terdapat jumlah nasabah pria yang lebih banyak dibandingkan
wanita, dimana nasabah pria memiliki charges yang lebih tinggi
dibandingkan wanita yaitu 0-40000an terhadap 0-20000an, meskipun ada
outlier biaya charges pada wanita lebih tinggi dibandingkan pria. Namun,
kita perlu fokus terhadap range boxplot data yang menjadi kumpulan data
terbanyak.
Mari kita lihat persebaran data region terhadap biaya
charges.
plot(insurance$region, insurance$charges, horizontal=T)
💡 Insight:
* Kita dapat melihat bahwa data terbanyak terdapat pada
nasabah yang tinggal di region southeast dengan biaya charges berada
pada rentang 0-40000an. Sementara, data paling sedikit terdapat pada
nasabah yang tinggal di region southwest dengan biaya charges berada
pada rentang 0-20000an.
6. Model Building
Simple Linear Regression
Regresi linear sederhana adalah model dengan satu variabel
prediktor. Berikut adalah model dengan menggunakan satu
prediktor yaitu age.
model_age <- lm(formula=charges~age, data=insurance)
summary(model_age)#>
#> Call:
#> lm(formula = charges ~ age, data = insurance)
#>
#> Residuals:
#> Min 1Q Median 3Q Max
#> -8064 -6684 -5943 5466 47828
#>
#> Coefficients:
#> Estimate Std. Error t value Pr(>|t|)
#> (Intercept) 3190.02 938.40 3.399 0.000695 ***
#> age 257.23 22.53 11.419 < 0.0000000000000002 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Residual standard error: 11560 on 1335 degrees of freedom
#> Multiple R-squared: 0.08899, Adjusted R-squared: 0.08831
#> F-statistic: 130.4 on 1 and 1335 DF, p-value: < 0.00000000000000022
ggplot(data = insurance, mapping=aes(x = age, y = charges))+
geom_point()+
scale_color_brewer(palette="Accent")+
geom_smooth(method="lm", se=FALSE)+
labs(title="Plot Regresi Age vs Biaya Charges")+
theme_minimal()
💡 Insight:
Dengan Menguji Signifikansi Parameter, variabel charges memiliki nilai p-value 2.2e-16 < 0.05, sehingga disimpulkan bahwa age (umur) memiliki pengaruh yang signifikan terhadap besarnya biaya charges asuransi terhadap nasabah
Adj R-Squared = 0.08831, dengan kata lain hanya sebesar 8,83% dari variabel age dapat menjelaskan model (pengaruh biaya asuransi)
Walaupun secara signifikansi parameter, variabel age berpengaruh signifikan, akan tetapi dari nilai adjR2 nilai yang dihasilkan masih sangat kecil, sehingga perlu penambahan faktor variabel lainnya.
Multiple Linear Regression
Akan dibuat model dengan keseluruhan variabel, dengan variabel target
adalah charges dan variabel prediktor antara lain
age, sex, bmi,
children, smoker, region.
model_all <- lm(formula=charges~.,
data=insurance)
summary(model_all)#>
#> Call:
#> lm(formula = charges ~ ., data = insurance)
#>
#> Residuals:
#> Min 1Q Median 3Q Max
#> -11305.1 -2850.3 -979.9 1395.0 29992.8
#>
#> Coefficients:
#> Estimate Std. Error t value Pr(>|t|)
#> (Intercept) -11936.56 988.23 -12.079 < 0.0000000000000002 ***
#> age 256.76 11.91 21.555 < 0.0000000000000002 ***
#> sexmale -129.48 333.20 -0.389 0.697630
#> bmi 339.25 28.61 11.857 < 0.0000000000000002 ***
#> children 474.82 137.90 3.443 0.000593 ***
#> smokeryes 23847.33 413.35 57.693 < 0.0000000000000002 ***
#> regionnorthwest -349.23 476.82 -0.732 0.464053
#> regionsoutheast -1035.27 478.87 -2.162 0.030804 *
#> regionsouthwest -960.08 478.11 -2.008 0.044836 *
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Residual standard error: 6064 on 1328 degrees of freedom
#> Multiple R-squared: 0.7507, Adjusted R-squared: 0.7492
#> F-statistic: 500 on 8 and 1328 DF, p-value: < 0.00000000000000022
💡 Hasil interpretasi dari summary(model_all):
- Variabel yang signifikan mempengaruhi charges adalah age, bmi, children, smoker, region
- Ketika variabel age naik 1 satuan, maka charges naik sebesar 256.76 dengan variabel prediktor lainnya tetap
- Ketika variabel bmi naik 1 satuan, maka charges naik sebesar 339.25 dengan variabel prediktor lainnya tetap
- sexfemale tidak masuk sebagai prediktor, artinya dijadikan basis, koefisien sexmale = -129.48, artinya pria menurunkan charges sebesar 129.48 apabila dibandingan dengan wanita
- smokerno dijadikan basis, koefisien smokeryes = 23847.33, artinya perokok menaikkan charges sebesar 23847.33 apabila dibandingkan bukan perokok
- regionnortheast dijadikan basis, koefisien regionnorthwest = -349.23, artinya regionnorthwest menurunkan charges sebesar 349.23 apabila dibandingkan regionnortheast
- regionnortheast dijadikan basis, koefisien regionsoutheast = -1035.27, artinya regionsoutheast menurunkan charges sebesar 1035.27 apabila dibandingkan regionnortheast
- regionnortheast dijadikan basis, koefisien regionsouthwest = -960.08, artinya regionsouthwest menurunkan charges sebesar 960.08 apabila dibandingkan regionnortheast
- Adjusted R-squared: 0.7492, artinya model kita berhasil menangkap informasi/varians sebesar 74.92% untuk memprediksi variabel target
7. Evaluasi Model Keseluruhan
Performa model
Kinerja model (seberapa baik model memprediksi variabel target) dapat dihitung dengan menggunakan nilai RMSE (Root Mean Square Error) dengan formula berikut:
\[ RMSE = \sqrt{\frac{1}{n} \sum (\hat prediction - actual)^2} \] RMSE merupakan suatu nilai pengujian performa yang lebih baik dibandingkan MAE (Mean Absolute Error). Hal ini disebabkan nilai RMSE mengkuadratkan selisih antara nilai aktual dan nilai prediksi, artinya prediksi dengan error yang lebih tinggi akan dikenakan sanksi yang besar.
# prediksi
insurance$pred_charges <- predict(model_all, insurance)
# menghitung RMSE
sqrt(mean((insurance$pred_charge - insurance$charges)^2))#> [1] 6043.85
range(insurance$charges)#> [1] 1121.874 63770.428
Berdasarkan hasil ini, model_all masih memberikan kesalahan yang
cukup tinggi untuk prediksi dan oleh karena itu masih perlu perbaikan.
Selanjutnya, kita akan melakukan pengujian asumsi terhadap
model_all.
Pengujian Asumsi
Uji asumsi terdiri dari 5 yaitu:
- Linearitas
- Normalitas
Residual
- Autokorelasi
- Homoskedastisitas Residual
-
Multikolinearitas
Note: Hanya perlu cek asumsi kepada model yang akan digunakan, tidak perlu semua kombinasi model dicek asumsinya. Pada bagian ini, kita akan cek asumsi untuk
model_all
Linearitas
Pengecekan asumsi linearitas sudah diperiksa sebelum membangun model menggunakan matriks korelasi pada langkah EDA dan juga scatter plot yang dibuat menggunakan variabel prediktor dan target. Akan tetapi akan dilakukan pemeriksaan cor.test() pada salah satu variabel prediktor dengan target.
Hipotesis
H0 : tidak ada korelasi yang signifikan (p=0)
H1 : terdapat korelasi signifikan (p=!0)
α= 0.05
Statistik Uji: Pearson dengan nilai p-value
cor.test(insurance$bmi, insurance$charges)#>
#> Pearson's product-moment correlation
#>
#> data: insurance$bmi and insurance$charges
#> t = 7.3961, df = 1335, p-value = 0.0000000000002468
#> alternative hypothesis: true correlation is not equal to 0
#> 95 percent confidence interval:
#> 0.1463465 0.2493595
#> sample estimates:
#> cor
#> 0.1984008
Kesimpulan: nilai p-value = 0.0000000000002468 < alpha = 0.95,
sehingga H0 ditolak. Sehingga terdapat korelasi yang signifikan antara
variabel bmi dan charges.
Selain itu, akan dilakukan pengecekan asumsi linearitas dengan
membuat plot residual vs fitted untuk model_all.
resfit <- data.frame(residual = model_all$residuals, fitted = model_all$fitted.values)
resfit %>% ggplot(aes(fitted, residual)) +
geom_point() +
geom_hline(aes(yintercept = 0, colour= "red")) +
theme_minimal() +
labs(title = "Residual vs Fitted Plot") +
theme(legend.position = "none")
💡 Insight:
* Dari plot di atas dapat dilihat bahwa residual/error
tidak memantul secara acak di sekitar 0 (tidak seragam) sehingga akan
menghasilkan rata-rata tidak sama dengan 0. Maka syarat E(ϵ)=0 tidak
terpenuhi. Disimpulkan bahwa data kita mungkin tidak linear, sehingga
asumsi tidak terpenuhi.
Normalitas Residual
Berikut adalah plot histogram dan normal probability plot (normal Q-Q plot) untuk melihat distribusi dari error.
par(mfrow=c(1,2))
hist(model_all$residuals, breaks = 10)
qqnorm(residuals(model_all), main="Normal Q-Q Plot")
qqline(residuals(model_all))
💡 Insight:
* Dapat dilihat dari plot, bahwa terdapat beberapa
residual yang tidak berada pada garis. Hal itu mengindikasikan bahwa
mungkin saja distribusi dari eror tidak normal. Untuk lebih meyakinkan,
akan dilakukan pengujian normalitas dengan menggunakan shapiro wilk
test.
Hipotesis:
H0: error berdistribusi normal
H1: error TIDAK berdistribusi normal
α= 0.05
Statistik Uji: Shapiro Wilk dengan nilai p-value
# shapiro test dari residual
shapiro.test(model_all$residuals)#>
#> Shapiro-Wilk normality test
#>
#> data: model_all$residuals
#> W = 0.89909, p-value < 0.00000000000000022
karena p-value < 0.05, sehingga kita tolak H0 atau asumsi normality tidak terpenuhi.
Autokorelasi
Hipotesis
H0 : tidak ada autokorelasi
H1 : ada auatokorelasi
α= 0.05
Statistik Uji: Durbin Watson dengan nilai p-value
durbinWatsonTest(model_all)#> lag Autocorrelation D-W Statistic p-value
#> 1 -0.04585675 2.088973 0.106
#> Alternative hypothesis: rho != 0
Aturan Keputusan Nilai p-value = 0.102 > 0.05 sehingga H0 gagal ditolak
Kesimpulan: Karena H0 gagal ditolak, sehingga tidak terdapat autokorelasi pada model. Asumsi terpenuhi
Homoskedastisitas
Hipotesis
H0: variansi residual seragam (homoskedastisitas)
H1: variansi residual tidak seragam (heteroskedastisitas)
α= 0.05
Statistik Uji: Breusch Pagan dengan nilai p-value
bptest(model_all)#>
#> studentized Breusch-Pagan test
#>
#> data: model_all
#> BP = 121.57, df = 8, p-value < 0.00000000000000022
Aturan Keputusan Nilai p-value = 0.00000000000000022 < 0.05 sehingga H0 ditolak
Kesimpulan Karena H0 ditolak, sehingga residual model yang kita miliki memiliki variansi yang tidak seragam (heteroskedastisitas). Asumsi tidak terpenuhi.
Multikolinearitas
Multikolinearitas adalah kondisi adanya korelasi antar prediktor yang kuat. Hal ini tidak diinginkan karena menandakan prediktor redundan pada model, yang seharusnya dapat dipilih salah satu saja dari variable yang hubungannya amat kuat tersebut. Harapannya tidak terjadi multikolinearitas.
Kondisi yang diharapkan: VIF < 10
vif(model_all)#> GVIF Df GVIF^(1/(2*Df))
#> age 1.016794 1 1.008362
#> sex 1.008944 1 1.004462
#> bmi 1.106742 1 1.052018
#> children 1.004017 1 1.002006
#> smoker 1.012100 1 1.006032
#> region 1.099037 3 1.015864
Dari uji VIF, prediktor di model backward lolos uji asumsi multikolinearitas (tidak ada nilai VIF > 10)
Kesimpulan:
* Dari kelima uji asumsi di atas, dapat disimpulkan
bahwa model_all tidak memenuhi uji Normalitas,
uji linearitas dan uji homoskedastisitas.
Sehingga, perlu dilukan improvement pada model.
8. Model Improvement
Dari analisis residual yang dilakukan, disimpulkan bahwa residual dari model_all tidak memenuhi uji asumsi. Dengan demikian akan dilakukan transformasi data untuk variabel prediktor dan respon. Salah satu jenis transformasi yang dapat dilakukan adalah transformasi logaritmik.
Berdasarkan hasil summary model_all diketahui bahwa
nilai p-value terbesar terdapat pada variabel sex, namun
karena variabel sex merupakan tipe data kategorik sehingga
tidak dapat dilakukan logaritmik, kemudian akan dipertimbangkan untuk
melakukan transformasi logaritmik pada variabel target charges karena
nilai nya yang terlalu besar.
Tuning Model
Transformasi dengan Komponen Logaritmik
trans_model_all <- lm(formula=log(charges)~., data=insurance)
summary(trans_model_all)#>
#> Call:
#> lm(formula = log(charges) ~ ., data = insurance)
#>
#> Residuals:
#> Min 1Q Median 3Q Max
#> -1.07416 -0.19619 -0.04969 0.06655 2.16494
#>
#> Coefficients: (1 not defined because of singularities)
#> Estimate Std. Error t value Pr(>|t|)
#> (Intercept) 7.0314797 0.0723842 97.141 < 0.0000000000000002 ***
#> age 0.0345390 0.0008725 39.585 < 0.0000000000000002 ***
#> sexmale -0.0745638 0.0244054 -3.055 0.00229 **
#> bmi 0.0134013 0.0020957 6.395 0.000000000222 ***
#> children 0.1015405 0.0101005 10.053 < 0.0000000000000002 ***
#> smokeryes 1.5537619 0.0302763 51.319 < 0.0000000000000002 ***
#> regionnorthwest -0.0620490 0.0349257 -1.777 0.07586 .
#> regionsoutheast -0.1573100 0.0350753 -4.485 0.000007923624 ***
#> regionsouthwest -0.1289664 0.0350196 -3.683 0.00024 ***
#> pred_charges NA NA NA NA
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Residual standard error: 0.4442 on 1328 degrees of freedom
#> Multiple R-squared: 0.7676, Adjusted R-squared: 0.7662
#> F-statistic: 548.4 on 8 and 1328 DF, p-value: < 0.00000000000000022
Dari trans_model_all didapatkan persamaan regresi sebagai berikut:
ln(charges)=7.0314 + 0.03453(age) - 0.0745(sexmale) + 0.0134(bmi) + 0.1015(children) + 1.5537(smokeryes)- 0.06204(regionnorthwest) - 0.1573(regionsoutheast) - 0.1289(regionsouthwest)
Berdasarkan summary model_all, nilai p-value dari
seluruh variable prediktor < 0.05 sehingga dapat disimpulkan bahwa
seluruh variabel tersebut memiliki pengaruh terhadap variabel
target.
trans_model_all <- lm(formula=log(charges)~., data=insurance)
summary(trans_model_all)#>
#> Call:
#> lm(formula = log(charges) ~ ., data = insurance)
#>
#> Residuals:
#> Min 1Q Median 3Q Max
#> -1.07416 -0.19619 -0.04969 0.06655 2.16494
#>
#> Coefficients: (1 not defined because of singularities)
#> Estimate Std. Error t value Pr(>|t|)
#> (Intercept) 7.0314797 0.0723842 97.141 < 0.0000000000000002 ***
#> age 0.0345390 0.0008725 39.585 < 0.0000000000000002 ***
#> sexmale -0.0745638 0.0244054 -3.055 0.00229 **
#> bmi 0.0134013 0.0020957 6.395 0.000000000222 ***
#> children 0.1015405 0.0101005 10.053 < 0.0000000000000002 ***
#> smokeryes 1.5537619 0.0302763 51.319 < 0.0000000000000002 ***
#> regionnorthwest -0.0620490 0.0349257 -1.777 0.07586 .
#> regionsoutheast -0.1573100 0.0350753 -4.485 0.000007923624 ***
#> regionsouthwest -0.1289664 0.0350196 -3.683 0.00024 ***
#> pred_charges NA NA NA NA
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Residual standard error: 0.4442 on 1328 degrees of freedom
#> Multiple R-squared: 0.7676, Adjusted R-squared: 0.7662
#> F-statistic: 548.4 on 8 and 1328 DF, p-value: < 0.00000000000000022
Model Backward
Selanjutnya, akan dilakukan backward regression dengan tujuan
menemukan model terbaik pada trans_model_all. Dilakukan
metode backward regression untuk pemilihan model menggunakan kriteria
AIC. Backward regression ialah metode yang akan mengeluarkan variabel
bebas yang tidak berpengaruh signifikan terhadap variabel respon secara
satu per satu dilihat dari nilai p-value masing-masing variabel bebas,
variabel bebas yang pertama dikeluarkan ialah yang memiliki p-value
paling besar dan melebihi taraf signifikansi.
set.seed(123)
trans_model_backward <- step(object=trans_model_all,
direction="backward",
trace=F)
summary(trans_model_backward)#>
#> Call:
#> lm(formula = log(charges) ~ age + sex + bmi + children + smoker +
#> region, data = insurance)
#>
#> Residuals:
#> Min 1Q Median 3Q Max
#> -1.07416 -0.19619 -0.04969 0.06655 2.16494
#>
#> Coefficients:
#> Estimate Std. Error t value Pr(>|t|)
#> (Intercept) 7.0314797 0.0723842 97.141 < 0.0000000000000002 ***
#> age 0.0345390 0.0008725 39.585 < 0.0000000000000002 ***
#> sexmale -0.0745638 0.0244054 -3.055 0.00229 **
#> bmi 0.0134013 0.0020957 6.395 0.000000000222 ***
#> children 0.1015405 0.0101005 10.053 < 0.0000000000000002 ***
#> smokeryes 1.5537619 0.0302763 51.319 < 0.0000000000000002 ***
#> regionnorthwest -0.0620490 0.0349257 -1.777 0.07586 .
#> regionsoutheast -0.1573100 0.0350753 -4.485 0.000007923624 ***
#> regionsouthwest -0.1289664 0.0350196 -3.683 0.00024 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Residual standard error: 0.4442 on 1328 degrees of freedom
#> Multiple R-squared: 0.7676, Adjusted R-squared: 0.7662
#> F-statistic: 548.4 on 8 and 1328 DF, p-value: < 0.00000000000000022
Berdasarkan hasil model step backward, diperoleh bahwa tidak terjadi pengurangan variabel prediktor.
Model Forward
Untuk dapat melakukan pemodelan step forward, pertama kita perlu melakukan model tanpa prediktor seperti berikut ini.
trans_model_nopredictor <- lm(formula=log(charges)~1, data=insurance)Setelah model tanpa prediktor dibuat, mari lakukan model step forward
set.seed(123)
trans_model_forward <- step(object=trans_model_nopredictor,
direction="forward",
scope=list(lower=trans_model_nopredictor, upper=trans_model_all),
trace=F)
summary(trans_model_forward)#>
#> Call:
#> lm(formula = log(charges) ~ pred_charges + age + children + bmi +
#> smoker + sex, data = insurance)
#>
#> Residuals:
#> Min 1Q Median 3Q Max
#> -1.07838 -0.19878 -0.04986 0.06552 2.15866
#>
#> Coefficients:
#> Estimate Std. Error t value Pr(>|t|)
#> (Intercept) 8.70846907 0.35654448 24.425 < 0.0000000000000002 ***
#> pred_charges 0.00014064 0.00002902 4.846 0.00000141 ***
#> age -0.00156135 0.00752835 -0.207 0.835732
#> children 0.03479435 0.01705488 2.040 0.041534 *
#> bmi -0.03442271 0.00956830 -3.598 0.000333 ***
#> smokeryes -1.80068913 0.69201373 -2.602 0.009368 **
#> sexmale -0.05631231 0.02466837 -2.283 0.022601 *
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Residual standard error: 0.4439 on 1330 degrees of freedom
#> Multiple R-squared: 0.7676, Adjusted R-squared: 0.7665
#> F-statistic: 732 on 6 and 1330 DF, p-value: < 0.00000000000000022
Model Both
set.seed(123)
trans_model_both <- step(object=trans_model_nopredictor,
direction="both",
scope=list(upper=trans_model_all),
trace=F)
summary(trans_model_both)#>
#> Call:
#> lm(formula = log(charges) ~ pred_charges + children + bmi + smoker +
#> sex, data = insurance)
#>
#> Residuals:
#> Min 1Q Median 3Q Max
#> -1.07810 -0.20000 -0.05044 0.06386 2.15701
#>
#> Coefficients:
#> Estimate Std. Error t value Pr(>|t|)
#> (Intercept) 8.635774819 0.065303360 132.241 < 0.0000000000000002 ***
#> pred_charges 0.000134659 0.000003357 40.108 < 0.0000000000000002 ***
#> children 0.037617670 0.010270102 3.663 0.000259 ***
#> bmi -0.032500687 0.002379846 -13.657 < 0.0000000000000002 ***
#> smokeryes -1.658250130 0.084789200 -19.557 < 0.0000000000000002 ***
#> sexmale -0.057058873 0.024395548 -2.339 0.019488 *
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Residual standard error: 0.4438 on 1331 degrees of freedom
#> Multiple R-squared: 0.7675, Adjusted R-squared: 0.7667
#> F-statistic: 879 on 5 and 1331 DF, p-value: < 0.00000000000000022
Performa Model
Untuk semua model kandidat dilakukan perbandingan performa untuk semua model tersebut. Tujuannya adalah mencari model regresi terbaik untuk memodelkan data.
model_comparison <- compare_performance(trans_model_nopredictor, trans_model_all, trans_model_backward, trans_model_forward, trans_model_both)
as.data.frame(model_comparison) %>%
select("Name","AIC","BIC","R2","R2_adjusted","RMSE")#> Name AIC BIC R2 R2_adjusted RMSE
#> 1 trans_model_nopredictor 27903.70 27914.10 0.0000000 0.0000000 0.9183550
#> 2 trans_model_all 25968.45 26020.43 0.7676303 0.7662305 0.4426907
#> 3 trans_model_backward 25968.45 26020.43 0.7676303 0.7662305 0.4426907
#> 4 trans_model_forward 25964.88 26006.46 0.7675559 0.7665073 0.4427615
#> 5 trans_model_both 25962.92 25999.31 0.7675484 0.7666751 0.4427687
Dapat dilihat bahwa model yang terbaik ialah trans_model_both karena
memiliki tiga performa kriteria yang lebih unggul dibandingkan performa
kriteria pada model yang lain, yaitu nilai Adj R-Square terbesar, nilai
AIC terkecil, dan nilai BIC terkecil. Sehingga disimpulkan bahwa model
regresi terbaik untuk memodelkan data pada kasus ini ialah
trans_model_both. Berikut detailnya:
* RMSE terkecil:
trans_model_all, trans_model_backward
*
Adj R-Square terbesar: trans_model_both
* AIC terkecil:
trans_model_both
* BIC terkecil:
trans_model_both
Dari model trans_model_both terdapat pengurangan
variabel prediktor sehingga yang tersisa adalah children,
bmi, smoker, dan sex. Keempat
variabel tersebut kemudian dimasukkan ke dalam
step_both2.
step_both2 <- lm(formula=log(charges) ~ children + bmi + smoker + sex, data=insurance)
summary(step_both2)#>
#> Call:
#> lm(formula = log(charges) ~ children + bmi + smoker + sex, data = insurance)
#>
#> Residuals:
#> Min 1Q Median 3Q Max
#> -1.99441 -0.43829 0.05817 0.45328 1.74731
#>
#> Coefficients:
#> Estimate Std. Error t value Pr(>|t|)
#> (Intercept) 8.10434 0.09499 85.313 < 0.0000000000000002 ***
#> children 0.11790 0.01496 7.879 0.00000000000000683 ***
#> bmi 0.01970 0.00296 6.655 0.00000000004125752 ***
#> smokeryes 1.52011 0.04480 33.933 < 0.0000000000000002 ***
#> sexmale -0.09735 0.03621 -2.688 0.00727 **
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Residual standard error: 0.6592 on 1332 degrees of freedom
#> Multiple R-squared: 0.4866, Adjusted R-squared: 0.4851
#> F-statistic: 315.6 on 4 and 1332 DF, p-value: < 0.00000000000000022
Pengujian Asumsi
Linearitas
resfit1 <- data.frame(residual = step_both2$residuals, fitted = step_both2$fitted.values)
resfit1 %>% ggplot(aes(fitted, residual)) +
geom_point() +
geom_hline(aes(yintercept = 0, colour= "red")) +
theme_minimal() +
labs(title = "Residual vs Fitted Plot") +
theme(legend.position = "none") 💡 Insight:
* Dari plot di atas dapat dilihat bahwa
residual/error cukup memantul secara acak di sekitar 0 (seragam)
sehingga akan menghasilkan rata-rata dengan 0. Maka syarat E(ϵ)=0
terpenuhi. Disimpulkan bahwa model kita linear. Asumsi terpenuhi.
Normalitas Residual
Berikut adalah plot histogram dan normal probability plot (normal Q-Q plot) untuk melihat distribusi dari error.
par(mfrow=c(1,2))
hist(step_both2$residuals, breaks = 10)
qqnorm(residuals(step_both2), main="Normal Q-Q Plot")
qqline(residuals(step_both2))
💡 Insight:
* Jika dibandingkan dengan plot normalitas residual pada
model_all, distribusi error nya jauh lebih baik, namun
masih terdapat beberapa residual yang tidak berada pada garis. Untuk
lebih meyakinkan, akan dilakukan pengujian normalitas dengan menggunakan
shapiro wilk test.
Hipotesis:
H0: error berdistribusi normal
H1: error TIDAK berdistribusi normal
α= 0.05
Statistik Uji: Shapiro Wilk dengan nilai p-value
#Shapiro wilk test
shapiro.test(step_both2$residuals)#>
#> Shapiro-Wilk normality test
#>
#> data: step_both2$residuals
#> W = 0.99525, p-value = 0.0003208
Aturan Keputusan p-value > 0.05; H0 ditolak.
Kesimpulan Maka dari itu, error/residual tidak berdistribusi normal. Asumsi normalitas residual tidak terpenuhi.
Autokorelasi
Hipotesis
H0 : tidak ada autokorelasi
H1 : ada auatokorelasi
α= 0.05
Statistik Uji: Durbin Watson dengan nilai p-value
durbinWatsonTest(step_both2)#> lag Autocorrelation D-W Statistic p-value
#> 1 -0.007029496 2.013713 0.77
#> Alternative hypothesis: rho != 0
Aturan Keputusan Nilai p-value = 0.758 > 0.05 sehingga H0 gagal ditolak
Kesimpulan: Karena H0 gagal ditolak, sehingga tidak terdapat autokorelasi pada model. Asumsi terpenuhi
Homoskedastisitas
Hipotesis
H0: variansi residual seragam (homoskedastisitas)
H1: variansi residual tidak seragam (heteroskedastisitas)
α= 0.05
Statistik Uji: Breusch Pagan dengan nilai p-value
bptest(step_both2)#>
#> studentized Breusch-Pagan test
#>
#> data: step_both2
#> BP = 214.66, df = 4, p-value < 0.00000000000000022
Aturan Keputusan Nilai p-value 2.2e-16 < 0.05 sehingga H0 ditolak
Kesimpulan: Karena H0 ditolak, sehingga residual model yang kita miliki memiliki variansi yang tidak seragam (heteroskedastisitas). Asumsi tidak terpenuhi.
Multikolinearitas
vif(step_both2)#> children bmi smoker sex
#> 1.000497 1.002300 1.005938 1.008341
Kesimpulan:: Dari output diketahui bahwa semua nilai VIF < 10.
Dengan demikian tidak terdapat gejala multikolinearitas pada
masing-masing variabel bebas yang terdapat pada step_both2.
Asumsi terpenuhi
9. Interpretasi Model Akhir
- Dari pengujian asumsi
step_both2diketahui bahwa terdapat beberapa asumsi yang tidak terpenuhi yaitu uji normalitas dan homoskedastisitas. Sehingga, model tidak bisa digunakan di dataset untuk penelitian, namun masih dapat digunakan untuk keperluan bisnis. Selanjutnya akan dilakukan interpretasi model berikut:
ln(charges)= 8.10434 + 0.11790(children) + 0.01970(bmi) + 1.52011(smokeryes) - 0.09735(sex)
Apabila variabel jumlah tanggungan anak bertambah 1 satuan, maka rata-rata banyaknya biaya yang dikeluarkan oleh pihak asuransi per individu naik sebesar e^(0.11790) = 1.12513 kali dengan variabel lain tetap. Apabila variabel bmi bertambah 1 satuan, maka rata-rata banyaknya biaya yang dikeluarkan oleh pihak asuransi per individu naik sebesar e^(0.01970) = 1.01989 kali dengan variabel lain tetap.
10. Kesimpulan
- Berdasarkan proses analisis faktor-faktor pada data banyaknya biaya
yang dikeluarkan oleh pihak asuransi per individu, didapatkan hasil
bahwa faktor yang berpengaruh secara signifikan terhadap biaya
chargesyaitu jumlah tanggungan anak, nilai bmi, status perokok dan jenis kelamin.