Model linear yang sudah disesuaikan tetap perlu diperiksa apakah asumsi-asumsinya terpenuhi, dan bahan pemeriksaan utamanya adalah residual, yaitu selisih nilai observasi dengan nilai prediksi model. Topik ini menghitung residual dan nilai prediksi dengan resid() dan fitted.values(), menggambar plot residual terhadap nilai prediksi dengan ggplot2, memeriksa normalitas residual melalui plot QQ, dan menutupnya dengan uji numerik Shapiro-Wilk. Pola yang mengkhawatirkan pada plot, seperti lengkungan dan bentuk kerucut, beserta maknanya dijelaskan sepanjang pembahasan.
Empat asumsi model linear#
Inferensi pada summary(), termasuk p-value dan interval kepercayaan, hanya sah apabila empat asumsi model linear terpenuhi. Asumsi linearitas menyatakan hubungan respons dengan prediktor berbentuk garis lurus, sehingga kurva pada data tidak tertangkap dengan baik oleh model linear. Asumsi homoskedastisitas menyatakan sebaran residual yang sama besar di sepanjang rentang prediktor, sedangkan sebaran yang melebar atau menyempit disebut heteroskedastisitas. Asumsi normalitas residual menyatakan gangguan acak yang mengikuti distribusi normal, dan asumsi independensi menyatakan residual satu observasi tidak memengaruhi observasi lainnya, misalnya karena urutan waktu.
Keempat asumsi tersebut tidak diperiksa dari tabel koefisien, melainkan dari residual itu sendiri. Model dengan koefisien signifikan dan R-squared tinggi tetap dapat melanggar asumsinya, dan kesimpulannya bisa menyesatkan. Di sinilah plot residual berperan sebagai alat utama, karena pelanggaran asumsi hampir selalu meninggalkan jejak pola yang dapat dilihat.
Model yang diperiksa#
Data dan model yang diperiksa sama dengan topik regresi linear sederhana, yaitu 30 siswa dengan jam belajar 1 sampai 8 jam per minggu dan nilai ujiannya. Model nilai ~ jam disesuaikan kembali dengan seed yang sama, sehingga seluruh angkanya identik dengan topik tersebut.
library(tidyverse)
set.seed(2026)
n <- 30
nama <- c("Ali", "Budi", "Citra", "Dewi", "Eka", "Fajar", "Gita", "Hana", "Indra", "Joko",
"Kartika", "Laila", "Maya", "Nanda", "Oki", "Putri", "Rahmat", "Sari", "Tono", "Umar",
"Vina", "Wawan", "Yuni", "Zaki", "Bagas", "Dian", "Farhan", "Gading", "Halim", "Intan")
belajar <- tibble(
siswa = nama,
jam = round(runif(n, min = 1, max = 8), 1),
nilai = round(52 + 4.5 * jam + rnorm(n, mean = 0, sd = 5), 1)
)
model <- lm(nilai ~ jam, data = belajar)
slice_head(belajar, n = 6)── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.2.1 ✔ readr 2.2.0
✔ forcats 1.0.1 ✔ stringr 1.6.0
✔ ggplot2 4.0.3 ✔ tibble 3.3.1
✔ lubridate 1.9.5 ✔ tidyr 1.3.2
✔ purrr 1.2.2
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
# A tibble: 6 × 3
siswa jam nilai
<chr> <dbl> <dbl>
1 Ali 5.9 85.3
2 Budi 4.9 77.1
3 Citra 2 62.1
4 Dewi 3 61.5
5 Eka 4.9 77.5
6 Fajar 1.2 55.8Menghitung residual dan nilai prediksi#
Dua vektor menjadi bahan baku seluruh diagnostik, yaitu fitted.values(model) yang memuat nilai prediksi garis untuk setiap siswa dan resid(model) yang memuat selisihnya terhadap nilai observasi. Keduanya ditempelkan ke dalam satu tabel agar mudah dipanggil berulang kali.
diag <- tibble(
fitted = fitted.values(model),
residual = resid(model)
)
slice_head(diag, n = 6)
mean(diag$residual)# A tibble: 6 × 2
fitted residual
<dbl> <dbl>
1 79.6 5.70
2 75.1 2.01
3 62.0 0.0844
4 66.5 -5.02
5 75.1 2.41
6 58.4 -2.61
[1] 2.016616e-17Enam baris pertama memperlihatkan polanya, yaitu siswa dengan nilai observasi di atas garis memperoleh residual positif dan siswa di bawah garis memperoleh residual negatif. Rata-rata residual bernilai 2,016616e-17, yang sebenarnya adalah nol dengan sisa pembulatan komputasi. Nilai nol ini bukan kebetulan, melainkan konsekuensi matematika kuadrat terkecil yang memaksa garis melalui pusat datanya, sehingga kecenderungan residual secara keseluruhan pasti habis.
Plot residual terhadap prediksi#
Plot residual terhadap nilai prediksi adalah pemeriksaan visual pertama dan paling penting. Sumbu horizontalnya berisi fitted dan sumbu tegaknya berisi residual, dengan garis putus-putus pada nol sebagai acuan.
p1 <- ggplot(diag, aes(x = fitted, y = residual)) +
geom_hline(yintercept = 0, linetype = "dashed", color = "gray40") +
geom_point(size = 2, color = "#4472C4") +
labs(
x = "Nilai prediksi (fitted)",
y = "Residual",
title = "Residual terhadap nilai prediksi model"
) +
theme_minimal()
ggplot2::ggsave("residual-fitted.svg", p1, width = 5, height = 3.2)Titik-titik pada grafik ini tersebar acak di sekitar garis nol tanpa pola yang jelas, dan lebarnya relatif sama di seluruh rentang nilai prediksi. Kondisi semacam ini mendukung asumsi linearitas dan homoskedastisitas. Dua pola yang mengkhawatirkan perlu diwaspadai, yaitu lengkungan berbentuk U yang menandakan hubungan sebenarnya tidak linear dan bentuk kerucut yang melebar di satu sisi yang menandakan heteroskedastisitas. Apabila salah satu pola itu muncul, transformasi variabel atau model yang berbeda menjadi pertimbangan berikutnya. Pemeriksaan pendamping yang lazim adalah plot residual terhadap prediktor aslinya, karena pola lengkung yang samar pada plot terhadap nilai prediksi kadang lebih jelas terlihat di sana. Apabila data dikumpulkan secara berurutan, misalnya pencatatan harian, residual juga perlu dilihat menurut urutannya untuk menilai asumsi independensi.
QQ plot dan normalitas residual#
Asumsi normalitas residual diperiksa dengan plot kuantil-kuantil (quantile-quantile), yaitu plot QQ. Kuantil residual sampel diletakkan di sumbu tegak, sedangkan kuantil teoretis dari distribusi normal diletakkan di sumbu horizontal, dan residual yang normal akan mengikuti garis lurus.
p2 <- ggplot(diag, aes(sample = residual)) +
stat_qq(size = 2, color = "#4472C4") +
stat_qq_line(color = "#C0504D") +
labs(
x = "Kuantil teoretis distribusi normal",
y = "Kuantil residual",
title = "Plot QQ residual model linear"
) +
theme_minimal()
ggplot2::ggsave("qq-residual.svg", p2, width = 5, height = 3.2)Titik-titik pada grafik menempel pada garis acuannya dengan deviasi kecil di ujung-ujungnya, pola yang wajar untuk sampel berukuran 30. Pemeriksaan numeriknya dapat dilakukan dengan uji Shapiro-Wilk melalui shapiro.test(), yang hipotesis nolnya menyatakan data berasal dari distribusi normal.
shapiro.test(diag$residual)
Shapiro-Wilk normality test
data: diag$residual
W = 0.96817, p-value = 0.4904Statistik W sebesar 0,968 dengan p-value 0,49 tidak memberi alasan untuk menolak normalitas residual. Hasil ini selaras dengan bacaan plot QQ di atas.
Ringkasan#
- Diagnostik model linear berpijak pada residual dari
resid()dan nilai prediksi darifitted.values(), yang rata-ratanya selalu nol pada model dengan intersep. - Plot residual terhadap nilai prediksi memeriksa linearitas dan homoskedastisitas, dengan lengkungan dan bentuk kerucut sebagai pola yang mengkhawatirkan.
- Plot QQ membandingkan kuantil residual dengan kuantil normal, dan titik yang mengikuti garis mendukung asumsi normalitas residual.
- Uji Shapiro-Wilk melengkapi pemeriksaan visual, dengan p-value 0,49 pada contoh ini sebagai ketiadaan bukti melawan normalitas, bukan bukti normalitasnya.
Referensi#
- An Introduction to R — CRAN — Bab Statistical models in R menguraikan fungsi-fungsi diagnostik seperti plot residual dan qqnorm untuk objek lm.
- R for Data Science, edisi ke-2 — Wickham, Çetinkaya-Rundel, Grolemund — Bab model membahas pemeriksaan asumsi model dan pembacaan pola residualnya.