Halo semua. Pada kesempatan kali ini, saya akan mencoba menganalisis salah satu dataset yang ada di R, yaitu mtcars
, tetapi menggunakan Python. Ini adalah hasil analisis data saya pertama kali (di luar perkuliahan) yang saya publikasikan.
Di sini, saya akan menyelidiki apa saja yang mempengaruhi penggunaan bahan bakar (mpg) dari sebuah mobil. Beberapa variabel yang ada di dataset mtcars
ini adalah
mpg : miles per galoon
cyl : number of cylinders
disp : displacement
hp : gross horsepower
drat : rear axle ratio
wt : weight (1000 lbs)
qsec : 1/4 mile time
vs : engine (0 = V-shaped, 1 = straight)
am : transmission (0 = automatic, 1 = manual)
gear : number of forward gears
carb : Number of carburetors
Untuk selanjutnya, mpg akan saya sebut sebagai variabel dependen sedangkan sisanya saya sebut sebagai variabel independen.
Saya akan menggunakan analisis regresi linear sederhana. Tentunya bagaimana menganalisis data tiap orang berbeda, tetapi saya menggunakan analisis ini karena analisis ini lebih mudah. Untuk dataset mtcars
bisa teman-teman lihat di sini dan untuk syntax yang saya buat dapat dilihat di sini.
Pertama saya akan mengimport beberapa modules python yang saya butuhkan. Modules yang akan saya gunakan adalah sebagai berikut:
import pandas as pd
import plotly.graph_objs as go
from plotly.subplots import make_subplots
import statsmodels.api as sm
from statsmodels.stats.outliers_influence import variance_inflation_factor
from statsmodels.sandbox.stats.runs import runstest_1samp
from sklearn.model_selection import train_test_split
from scipy.stats import shapiro
Data Train dan Data Test
Sebagai tahapan awal, saya akan membagi datanya menjadi 2, yaitu data train dan data test. Data train akan saya gunakan untuk membentuk model sedangkan data test akan saya gunakan untuk menguji model yang sudah terbentuk. Dari keseluruhan data, saya akan pilih 80% data secara acak sebagai data train, dan 20% data secara acak sebagai data test.
#input data
df = pd.read_excel ('mtcars.xlsx')
#bagi antara variabel independen dengan variabel dependen
X = df[['cyl','disp','hp','drat','wt','qsec','vs','am','gear','carb']]
Y = df['mpg']
#bagi data menjadi train dan test
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2)
#reset index
X_train = X_train.reset_index(drop = True)
X_test = X_test.reset_index(drop = True)
Y_train = Y_train.reset_index(drop = True)
Y_test = Y_test.reset_index(drop = True)
#menamai ulang variabel
X = X_train
Y = Y_train
Data train dan data test yang saya gunakan dapat teman-teman lihat di sini dan di sini.
Asumsi awal
Setelah membagi datanya, selanjutnya akan selidiki beberapa asumsi awal analisis regresi linear. Asumsi yang akan diselidiki adalah
- Cek apakah ada hubungan linear antara linearitas dari variabel dependen dengan variabel independen. (Linearitas)
- Cek apakah setiap variabel independen saling mempengaruhi satu sama lain. (Multikolinearitas)
Linearitas
Pertama saya akan mengecek apakah terdapat hubungan linear antara variabel dependen dengan variabel independen lainnya. Untuk menyelidikinya, kita bisa melihatnya dari scatter plot di bawah ini.
#siapkan figure subplot
fig = make_subplots(
rows = 5, cols = 2,
subplot_titles = ("Cyl and Mpg",
"Disp and Mpg",
"Hp and Mpg",
"Drat and Mpg",
"WT and Mpg",
"Qsec and Mpg",
"VS and Mpg",
"AM and Mpg",
"Gear and Mpg",
"Carb and Mpg")
)
#buat plot masing-masing subplot
index = 0
for i in range(1,6):
for j in range(1,3):
fig.add_trace(go.Scatter(x = X[X.keys()[index]], y = Y, mode = 'markers', marker = {'color' : 'black'}), row = i, col = j)
fig.update_xaxes(title_text = X.keys()[index], row = i, col = j)
fig.update_yaxes(title_text = 'mpg', row = i, col = j)
index = index+1
#atur layout
layout = {
'height' : 2000,
#'width' : 1000,
'title' : {
'text' : 'Scatter Plot',
'x' : 0.5
},
'showlegend' : False
}
fig.update_layout(layout)
fig.show()
Berdasarkan scatter plot di atas, tampak bahwa terdapat hubungan linear antara beberapa variabel independen dengan variabel mpg. Kita dapat simpulkan beberapa hal sebagai berikut:
- Terdapat hubungan linear negatif antara variabel cyl dan mpg. Artinya, semakin banyak silinder pada mobil, semakin sedikit bahan bakar yang terpakai.
- Terdapat hubungan linear negatif antara variabel disp dan mpg. Artinya, semakin besar displacement pada mobil, semakin sedikit bahan bakar yang terpakai.
- Terdapat hubungan linear negatif antara variabel hp dan mpg. Artinya, semakin besar horsepower mobil, semakin sedikit bahan bakar yang terpakai.
- Terdapat hubungan linear positif antara variabel drat dan mpg. Artinya, semakin besar rear axle gear ratio pada mobil, semakin banyak bahan bakar yang terpakai.
- Terdapat hubungan linear negatif antara variabel wt dan mpg. Artinya, semakin berat mobil, semakin sedikit bahan bakar yang terpakai.
- Terdapat hubungan linear positif antara variabel qsec dan mpg. Artinya, semakin lama mobil menempuh jarak 1/4 mil , semakin banyak bahan bakar yang terpakai.
- Konfigurasi silinder yang berbentuk V akan memakai bahan bakar lebih sedikit dibandingkan dengan konfigurasi silinder yang berbentuk garis lurus.
- Mobil matic akan memakai bahan bakar lebih sedikit dibandingkan dengan mobil manual.
- Mobil dengan 3 gigi akan memakai bahan bakar lebih sedikit dibandingkan dengan mobil dengan 5 gigi dibandingkan dengan mobil dengan 4 gigi.
- Terdapat hubungan linear negatif antara variabel carb dan mpg. Artinya, semakin banyak karburator pada mobil, semakin sedikit bahan bakar yang terpakai.
Sekilas mungkin untuk variabel gear tidak memiliki hubungan linear dengan mpg. Tapi kita asumsikan variabel gear memiliki hubungan linear dengan mpg.
Multikolinearitas
Selanjutnya, kita akan menyelidiki apakah variabel-variabel independen pada data kita saling mempengaruhi atau tidak. Kita akan mengecek nilai VIF dari masing-masing variabel. Jika VIF > 10, maka variabel tersebut memiliki hubungan dengan variabel independen lainnya. Kita akan membuang variabel dengan VIF terbesar kemudian kita akan cek kembali VIF variabel-variabel yang tersisa (Konstanta akan tetap dipertahankan). Kita akan ulangi terus sampai kita peroleh VIF dari semua variabel kurang dari 10. Berikut rangkuman nilai VIF dari setiap iterasi.
X = sm.add_constant(X)
#hitung VIF
VIF = pd.Series([variance_inflation_factor(X.values, i)
for i in range(X.shape[1])],
index=X.columns)
print(VIF,'\n')
#jika VIF konstanta terbesar, cari terbesar kedua
if list(VIF).index(max(VIF)) == 0:
new_VIF = VIF[1:]
drop_variable_VIF = max(new_VIF)
while drop_variable_VIF > 10 and len(X.keys())!=0:
#buang variabel dengan VIF terbesar dan lebih dari 10
drop_variable_index = list(VIF).index(drop_variable_VIF)
drop_variable = X.keys()[drop_variable_index]
X = X.drop(columns = drop_variable)
VIF = pd.Series([variance_inflation_factor(X.values, i)
for i in range(X.shape[1])],
index=X.columns)
print(VIF,'\n')
#jika VIF konstanta terbesar, cari terbesar kedua
if list(VIF).index(max(VIF)) == 0:
new_VIF = VIF[1:]
drop_variable_VIF = max(new_VIF)
Berikut rangkuman dari nilai VIF setiap iterasi.
Iterasi | Variabel | VIF |
---|---|---|
1 | const | 2149.280570 |
cyl | 19.691673 | |
disp | 22.176578 | |
hp | 10.308235 | |
drat | 4.114787 | |
wt | 17.319301 | |
qsec | 7.284777 | |
vs | 4.702383 | |
am | 5.234086 | |
gear | 7.002498 | |
carb | 11.759377 | |
2 | const | 2149.201123 |
cyl | 18.589723 | |
hp | 6.615471 | |
drat | 4.024375 | |
wt | 8.076653 | |
qsec | 6.744210 | |
vs | 4.654625 | |
am | 5.176873 | |
gear | 7.000588 | |
carb | 7.077009 | |
3 | const | 736.258880 |
hp | 6.553351 | |
drat | 3.142362 | |
wt | 7.695028 | |
qsec | 5.254881 | |
vs | 4.291331 | |
am | 4.951499 | |
gear | 5.176046 | |
carb | 6.275307 |
Dari hasil perhitungan di atas, dapat kita lihat bahwa ternyata nilai dari cyl dan disp dipengaruhi oleh variabel independen lainnya. Dengan demikian, kita perlu membuang variabel tersebut agar analisis regresi dapat dilakukan.
Variable Selection
Selanjutnya, untuk memilih variabel apa saja yang signifikan terhadap model, kita akan menggunakan stepwise regression, khususnya backward elimination. Pertama, kita akan membentuk model menggunakan semua variabel. Kemudian kita akan lihat apakah ada variabel yang tidak signifikan (jika p-value lebih dari ). Jika ada variabel yang tidak signifikan, kita keluarkan variabel tersebut (terutama yang p-value nya terbesar) kemudian kita bentuk model yang baru. Langkah ini diteruskan sampai semua variabel signifikan terhadap model.
model = []
loglikelihood = []
model.append(sm.OLS(Y,X).fit())
i = 0
variables_pvalue = list(model[i].pvalues)
loglikelihood.append(sm.OLS(Y,X).loglike(model[i].params))
while max(variables_pvalue) > 0.05 and len(X.keys())!=0:
#buang variabel yang tidak signifikan
drop_variable_pvalue = max(variables_pvalue)
drop_variable_index = variables_pvalue.index(drop_variable_pvalue)
drop_variable = X.keys()[drop_variable_index]
X = X.drop(columns = drop_variable)
model.append(sm.OLS(Y,X).fit())
i = i+1
variables_pvalue = list(model[i].pvalues)
loglikelihood.append(sm.OLS(Y,X).loglike(model[i].params))
for i in model:
print(i.summary())
Berikut hanya saya rangkum koefisien dan p-value dari masing-masing variabel tiap model. Untuk nilai statistik lainnya dapat dilihat pada syntax.
Model | Variabel | Koefisien | P-Value |
---|---|---|---|
1 | const | 5.0293 | 0.637 |
hp | 0.0155 | 0.306 | |
drat | 2.3856 | 0.079 | |
wt | -0.3515 | 0.754 | |
qsec | 0.1904 | 0.707 | |
vs | 2.4657 | 0.15 | |
am | 6.0699 | 0.003 | |
gear | 1.3572 | 0.274 | |
carb | -2.1244 | 0.002 | |
2 | const | 4.7143 | 0.648 |
hp | 0.0146 | 0.311 | |
drat | 2.4828 | 0.054 | |
qsec | 0.1141 | 0.791 | |
vs | 2.6869 | 0.079 | |
am | 6.2544 | 0.001 | |
gear | 1.4795 | 0.198 | |
carb | -2.2185 | 0 | |
3 | const | 7.0518 | 0.186 |
hp | 0.0132 | 0.31 | |
drat | 2.4601 | 0.049 | |
vs | 2.906 | 0.021 | |
am | 6.1124 | 0.001 | |
gear | 1.4651 | 0.189 | |
carb | -2.218 | 0 | |
4 | const | 10.1872 | 0.024 |
drat | 2.0471 | 0.078 | |
vs | 2.6007 | 0.031 | |
am | 5.9254 | 0.001 | |
gear | 1.3103 | 0.234 | |
carb | -1.8558 | 0 | |
5 | const | 12.9007 | 0.002 |
drat | 2.2434 | 0.055 | |
vs | 3.1553 | 0.006 | |
am | 7.1908 | 0 | |
carb | -1.6252 | 0 | |
6 | const | 19.864 | 0 |
vs | 4.1979 | 0 | |
am | 8.6664 | 0 | |
carb | -1.5869 | 0 |
Dari rangkuman model di atas, kita peroleh 6 model sebagai berikut:
- mpg = 5.0293 + 0.0155 hp + 2.3856 drat - 0.3515 wt + 0.1904 qsec + 2.4657 vs + 6.0699 am + 1.3572 gear - 2.1244 carb
- mpg = 4.7143 + 0.0146 hp + 2.4828 drat + 0.1141 qsec + 2.6869 vs + 6.2544 am + 1.4795 gear - 2.2185 carb
- mpg = 7.0518 + 0.0132 hp + 2.4601 drat + 2.9060 vs + 6.1124 am + 1.4651 gear - 2.2180 carb
- mpg = 10.1872 + 2.0471 drat + 2.6007 vs + 5.9254 am + 1.3103 gear - 1.8558 carb
- mpg = 12.9007 + 2.2434 drat + 3.1553 vs + 7.1908 am - 1.6252 carb
- mpg = 19.8640 + 4.1979 vs + 8.6664 am - 1.5869 carb
Pemilihan Model Terbaik
Walaupun semua variabel pada model ke-6 sudah signifikan, tetapi belum tentu model tersebut adalah model yang terbaik. Kita akan pilih model yang terbaik dengan membandingkan beberapa nilai statistik setiap modelnya, seperti:
- R-squared (semakin besar nilainya, semakin baik modelnya)
- Adj R-Squared (semakin besar nilainya, semakin baik modelnya)
- Sum squared error (SSE) (semakin kecil nilainya, semakin baik modelnya)
- Log-Likelihood (semakin kecil nilainya, semakin baik modelnya)
- AIC (semakin kecil nilainya, semakin baik modelnya)
- BIC (semakin kecil nilainya, semakin baik modelnya)
r_squared = []
adj_r_squared = []
sse = []
aic = []
bic = []
for i in model:
r_squared.append(i.rsquared)
adj_r_squared.append(i.rsquared_adj)
sse.append(i.ssr)
aic.append(i.aic)
bic.append(i.bic)
Berikut rangkuman nilai-nilai statistik dari setiap modelnya.
Model | R-Squared | Adj R-Squared | Sum Square Error | Log-Likelihood | AIC | BIC |
---|---|---|---|---|---|---|
1 | 0.938899 | 0.908349 | 59.546839 | -46.322056 | 110.644111 | 121.613994 |
2 | 0.938512 | 0.913194 | 59.923853 | -46.400949 | 108.801897 | 118.552904 |
3 | 0.938249 | 0.917666 | 60.180040 | -46.454275 | 106.908549 | 115.440680 |
4 | 0.934507 | 0.917272 | 63.827037 | -47.189726 | 106.379453 | 113.692708 |
5 | 0.929296 | 0.915156 | 68.905413 | -48.146700 | 106.293400 | 112.387779 |
6 | 0.914661 | 0.902470 | 83.168500 | -50.498374 | 108.996748 | 113.872251 |
Dari beberapa nilai statistik model di atas, diperoleh:
- Model 1 memiliki nilai R-Squared terbesar
- Model 3 memiliki nilai Adj R-Squared terbesar
- Model 1 memiliki nilai Sum Squared Error terkecil
- Model 6 memiliki nilai Log-Likelihood terkecil
- Model 5 memiliki nilai AIC terkecil
- Model 5 memiliki nilai BIC terkecil
Dapat dilihat bahwa model 6 hanya memenuhi 1 kriteria model terbaik, sedangkan model 1 dan model 5 memenuhi 2 kriteria model terbaik. Karena model 1 memiliki lebih banyak variabel independen, kita akan memilih model 1 sebagai model terbaik (untuk sementara).
Diagnostic Checking
Kita akan melakukan diagnostic checking pada model yang sudah kita pilih. Diagnostic checking yang kan kita lakukan adalah
- Cek apakah residual berdistribusi normal.
- Cek apakah terdapat autokorelasi dari residual.
- Cek homoskedastisitas dari residual.
Normalitas Residual
Untuk mengecek normalitas dari residual, kita akan melakukan uji shapiro-wilk. Hipotesis nol dari uji ini adalah residual berdistribusi normal. Hipotesis nol akan ditolak jika p-value < 0.05.
#cek normalitas residual model 1
result = shapiro(model[0].resid)
print('P-value :',result[1])
P-value : 0.8178114295005798
Karena p-value > 0.05, maka hipotesis nol tidak ditolak sehingga residual berdistribusi normal.
Autokorelasi Residual
Selanjutnya untuk mengecek autokorelasi dari residual, kita akan melakukan uji runs. Hipotesis nol dari uji ini adalah residual bersifat acak (tidak ada autokorelasi). Hipotesis akan ditolak jika p-value <0.05.
#cek autokorelasi residual model 1
result = runstest_1samp(model[0].resid)[1]
print('P-value :',result)
P-value : 0.9934688058918629
Karena p-value 0.05, maka hipotesis nol tidak ditolak sehingga tidak ada autokorelasi pada residual. Artinya residual-residual data tidak saling mempengaruhi.
Homoskedastisitas Residual
Selanjutnya untuk mengecek homoskedastisitas dari residual, kita perhatikan plot di bawah ini.
homos_variance_data = go.Scatter(
x = model[0].fittedvalues,
y = model[0].resid,
mode = 'markers',
marker = {'color' : 'black'}
)
layout = {
'title' : {
'text' : 'Homoskedasticity Scatter Plot',
'x' : 0.5
},
'xaxis' : {
'title' : 'Fitted Values'
},
'yaxis' : {
'title' : 'Residuals'
}
}
fig = go.Figure(data = homos_variance_data, layout = layout)
fig.show()
Berdasarkan plot di atas, dapat dilihat bahwa data tidak membentuk suatu pola tertentu sehingga data residual memiliki variansi yang sama (homoskedastisitas residual terpenuhi).
Karena model 1 memenuhi ketiga diagnostic checking, maka model 1 sudah merupakan model yang benar-benar baik.
Data Testing
Selanjutnya, kita coba test model 1 ini dengan data test yang sudah kita punya.
X = X_test
X = sm.add_constant(X)
Y = Y_test
Predicted_Values = model[0].predict(X)
True_Values = Y
Residuals = Predicted_Values-True_Values
Berikut tabel perbandingan antara Predicted Values dan True Values.
Predicted Values | True Values | Residuals |
---|---|---|
21.068265 | 21.4 | -0.331735 |
12.583638 | 10.4 | 2.183638 |
21.126499 | 24.4 | -3.273501 |
25.199310 | 15.8 | 9.399310 |
28.805596 | 21.4 | 7.405596 |
30.224956 | 22.8 | 7.424956 |
14.885272 | 17.3 | -2.414728 |
Dari tabel di atas, dapat dilihat bahwa nilai residual berada pada rentang -1 sampai 10.
Kesimpulan
Berdasarkan analisis yang sudah kita lakukan, kita peroleh model untuk mengestimasi nilai mpg adalah
mpg = 5.0293 + 0.0155 hp + 2.3856 drat - 0.3515 wt + 0.1904 qsec + 2.4657 vs + 6.0699 am + 1.3572 gear - 2.1244 carb.
Model di atas dapat diinterpretasikan sebagai berikut.
- Setiap penambahan 1 satuan variabel hp mengakibatkan variabel mpg bertambah sebesar 0.0155 dengan mengasumsikan variabel lainnya tetap.
- Setiap penambahan 1 satuan variabel drat mengakibatkan variabel mpg bertambah sebesar 2.3856 dengan mengasumsikan variabel lainnya tetap.
- Setiap penambahan 1 satuan variabel wt mengakibatkan variabel mpg berkurang sebesar 0.3515 dengan mengasumsikan variabel lainnya tetap.
- Setiap penambahan 1 satuan variabel qsec mengakibatkan variabel mpg bertambah sebesar 0.1904 dengan mengasumsikan variabel lainnya tetap.
- Setiap penambahan 1 satuan variabel vs mengakibatkan variabel mpg bertambah sebesar 2.4657 dengan mengasumsikan variabel lainnya tetap.
- Setiap penambahan 1 satuan variabel am mengakibatkan variabel mpg bertambah sebesar 6.0699 dengan mengasumsikan variabel lainnya tetap.
- Setiap penambahan 1 satuan variabel gear mengakibatkan variabel mpg bertambah sebesar 1.3572 dengan mengasumsikan variabel lainnya tetap.
- Setiap penambahan 1 satuan variabel carb mengakibatkan variabel mpg berkurang sebesar 2.1244 dengan mengasumsikan variabel lainnya tetap.
Memang sebenarnya model di atas masih kurang baik untuk digunakan karena residualnya masih terlalu besar. Metode stepwise regression juga kurang disarankan untuk digunakan dalam permasalahan nyata karena estimatornya bias dan penyeleksian variabelnya dapat mengakibatkan underfitting. Namun metode ini cocok digunakan untuk pemula dalam belajar analisis data (seperti saya heheheā¦.). Semoga bermaanfaat bagi kita semua.