Program Studi S1 Statistika · FMIPA · Universitas Padjadjaran
Mata Kuliah Analisis Data Kategori · Prof. I G.N. Mindra Jaya, Ph.D
Bagian ini membahas konsep dasar analisis data kategori yang memuat definisi, tabel kontingensi, distribusi peluang, ukuran asosiasi, hingga perhitungan manual dan analisis menggunakan R. Contoh yang digunakan adalah data hubungan antara keikutsertaan bimbingan belajar (bimbel) dan kelulusan Seleksi Nasional Penerimaan Mahasiswa Baru (SNPMB/PTN).
Definisi
Analisis data kategori (categorical data analysis) adalah sekumpulan metode statistik untuk menganalisis data yang nilainya berupa kategori atau kelompok, bukan angka kontinu. Data semacam ini mewakili karakteristik yang bisa dikelompokkan ke dalam dua kategori atau lebih yang saling eksklusif (Agresti, 2013).
Variabel kategori dibagi menjadi dua jenis utama:
| Karakteristik | Penjelasan |
|---|---|
| Diskrit | Nilainya terbatas, tidak ada nilai di antara dua kategori |
| Non-numerik | Berupa label atau kode, meski bisa dikodekan dengan angka |
| Mutually exclusive | Satu observasi hanya masuk ke satu kategori |
| Exhaustive | Semua kemungkinan nilai sudah tercakup |
| Distribusi khusus | Mengikuti distribusi Binomial atau Multinomial |
Referensi: Agresti, A. (2013). Categorical Data Analysis (3rd ed.). Wiley. | Agresti & Franklin (2014). Statistics: The Art and Science of Learning from Data. Pearson. | Hosmer & Lemeshow (2000). Applied Logistic Regression. Wiley.
Definisi
Tabel kontingensi (contingency table) adalah tabel yang merangkum hubungan antara dua variabel kategori atau lebih. Setiap sel berisi frekuensi observasi untuk kombinasi kategori tertentu. Tabel dengan \(r\) baris dan \(c\) kolom disebut tabel \(r \times c\) (Agresti, 2013).
Bentuk paling sederhana adalah tabel \(2 \times 2\), di mana kedua variabel masing-masing punya dua kategori:
| Y = 1 | Y = 2 | Total | |
|---|---|---|---|
| X = 1 | \(n_{11}\) | \(n_{12}\) | \(n_{1+}\) |
| X = 2 | \(n_{21}\) | \(n_{22}\) | \(n_{2+}\) |
| Total | \(n_{+1}\) | \(n_{+2}\) | \(n\) |
Keterangan: \(n_{ij}\) = frekuensi sel baris ke-\(i\) kolom ke-\(j\); \(n_{i+}\) dan \(n_{+j}\) = total marginal baris dan kolom; \(n\) = total keseluruhan.
Tabel berikut menunjukkan hubungan antara keikutsertaan bimbel dan kelulusan PTN pada 200 siswa:
| Lolos PTN | Tidak Lolos | Total | |
|---|---|---|---|
| Ikut Bimbel | 60 | 40 | 100 |
| Tidak Bimbel | 20 | 80 | 100 |
| Total | 80 | 120 | 200 |
Nilai sel: \(a = 60,\ b = 40,\ c = 20,\ d = 80,\ n = 200\).
Distribusi bersama menunjukkan probabilitas observasi jatuh pada sel \((i, j)\) tertentu:
\[\hat{\pi}_{ij} = \frac{n_{ij}}{n}\]
Dari tabel di atas:
\[\hat{\pi}_{11} = \frac{60}{200} = 0{,}30 \qquad \hat{\pi}_{12} = \frac{40}{200} = 0{,}20\]
\[\hat{\pi}_{21} = \frac{20}{200} = 0{,}10 \qquad \hat{\pi}_{22} = \frac{80}{200} = 0{,}40\]
Jumlah seluruh probabilitas bersama = 1.
Distribusi marginal adalah distribusi peluang untuk masing-masing variabel secara terpisah, diperoleh dengan menjumlahkan sel sepanjang baris atau kolom:
\[\hat{\pi}_{i+} = \frac{n_{i+}}{n} \quad \text{(marginal baris)} \qquad \hat{\pi}_{+j} = \frac{n_{+j}}{n} \quad \text{(marginal kolom)}\]
Dari contoh: \(P(\text{Ikut Bimbel}) = 0{,}50\); \(P(\text{Lolos PTN}) = 0{,}40\); \(P(\text{Tidak Lolos}) = 0{,}60\).
Probabilitas bersyarat adalah peluang \(Y\) mengambil nilai tertentu, diketahui nilai \(X\):
\[P(Y = j \mid X = i) = \frac{n_{ij}}{n_{i+}}\]
Dari contoh:
\[P(\text{Lolos PTN} \mid \text{Ikut Bimbel}) = \frac{60}{100} = 0{,}60 \qquad P(\text{Lolos PTN} \mid \text{Tidak Bimbel}) = \frac{20}{100} = 0{,}20\]
Independensi: Dua variabel dikatakan independen bila \(P(Y=j \mid X=i) = P(Y=j)\) untuk semua \(i\) dan \(j\). Di sini \(P(\text{Lolos PTN} \mid \text{Ikut Bimbel}) = 0{,}60 \neq P(\text{Lolos PTN}) = 0{,}40\), jadi keduanya tidak independen.
Dari tabel kontingensi dapat dihitung berbagai ukuran yang menggambarkan seberapa kuat hubungan antara dua variabel.
Definisi
Odds adalah perbandingan antara peluang suatu kejadian terjadi dengan peluang kejadian itu tidak terjadi.
\[\text{Odds} = \frac{\pi}{1 - \pi} = \frac{n_{i1}}{n_{i2}}\]
| Nilai Odds | Artinya |
|---|---|
| Odds = 1 | Sama mungkin terjadi maupun tidak |
| Odds > 1 | Lebih mungkin terjadi |
| Odds < 1 | Lebih kecil kemungkinannya terjadi |
Dari contoh:
Odds Ratio membandingkan odds antara dua kelompok:
\[\boxed{OR = \frac{ad}{bc}}\]
Interval kepercayaan 95% dihitung sebagai:
\[95\%\, CI: \quad \exp\!\left(\ln(\widehat{OR}) \pm 1{,}96 \times \sqrt{\tfrac{1}{a}+\tfrac{1}{b}+\tfrac{1}{c}+\tfrac{1}{d}}\right)\]
| Nilai OR | Artinya |
|---|---|
| OR = 1 | Tidak ada asosiasi |
| OR > 1 | Kelompok X = 1 punya odds lebih tinggi (asosiasi positif) |
| OR < 1 | Kelompok X = 1 punya odds lebih rendah (asosiasi negatif) |
Relative Risk membandingkan risiko (probabilitas) kejadian antara dua kelompok secara langsung:
\[\boxed{RR = \frac{a/(a+b)}{c/(c+d)}}\]
| Nilai RR | Artinya |
|---|---|
| RR = 1 | Risiko sama di kedua kelompok |
| RR > 1 | Kelompok X = 1 lebih berisiko |
| RR < 1 | Kelompok X = 1 lebih terlindungi |
Catatan: RR hanya valid untuk studi cohort atau cross-sectional. Pada studi case-control, OR dipakai sebagai pendekatan RR saat prevalensi penyakit rendah (rare disease assumption).
Studi cross-sectional dilakukan pada 200 siswa SMA untuk melihat hubungan antara keikutsertaan bimbingan belajar (bimbel) dan kelulusan Seleksi Nasional Penerimaan Mahasiswa Baru (PTN). Data tersedia pada tabel berikut.
| Lolos PTN | Tidak Lolos | Total | |
|---|---|---|---|
| Ikut Bimbel | 60 | 40 | 100 |
| Tidak Bimbel | 20 | 80 | 100 |
| Total | 80 | 120 | 200 |
Nilai sel: \(a = 60,\ b = 40,\ c = 20,\ d = 80,\ n = 200\).
1
Berapa peluang lolos PTN di masing-masing kelompok?
\[P(\text{Lolos PTN} \mid \text{Ikut Bimbel}) = \frac{60}{100} = \mathbf{0{,}60}\]
\[P(\text{Lolos PTN} \mid \text{Tidak Bimbel}) = \frac{20}{100} = \mathbf{0{,}20}\]
2
\[\text{Odds}_{\text{Ikut Bimbel}} = \frac{60}{40} = \mathbf{1{,}50}\]
\[\text{Odds}_{\text{Tidak Bimbel}} = \frac{20}{80} = \mathbf{0{,}25}\]
3
\[OR = \frac{60 \times 80}{40 \times 20} = \frac{4800}{800} = \mathbf{6{,}00}\]
\[SE_{\ln(OR)} = \sqrt{\frac{1}{60} + \frac{1}{40} + \frac{1}{20} + \frac{1}{80}} = \sqrt{0{,}1042} = 0{,}3228\]
\[\ln(6) = 1{,}7918 \quad \Rightarrow \quad 95\%\, CI:\ 1{,}7918 \pm 1{,}96 \times 0{,}3228 = (1{,}159\,;\,2{,}425)\]
\[95\%\, CI\ \text{untuk } OR = \left(e^{1{,}159}\,;\,e^{2{,}425}\right) = \mathbf{(3{,}19\,;\,11{,}30)}\]
4
\[RR = \frac{0{,}60}{0{,}20} = \mathbf{3{,}00}\]
5
Frekuensi harapan di bawah \(H_0\) (independensi):
\[E_{11} = \frac{100 \times 80}{200} = 40 \quad E_{12} = 60 \quad E_{21} = 40 \quad E_{22} = 60\]
\[\chi^2 = \frac{(60-40)^2}{40} + \frac{(40-60)^2}{60} + \frac{(20-40)^2}{40} + \frac{(80-60)^2}{60} = \mathbf{33{,}33}\]
Dengan \(df = 1\) dan nilai kritis \(\chi^2_{0{,}05} = 3{,}841\): karena \(33{,}33 > 3{,}841\), maka \(H_0\) ditolak ada hubungan yang signifikan antara keikutsertaan bimbel dan kelulusan PTN.
Ringkasan hasil:
6,00
Odds Ratio
3,00
Relative Risk
33,33
χ² Statistik
<0,001
p-value
# Buat matriks tabel kontingensi
data <- matrix(c(60, 40, 20, 80),
nrow = 2,
byrow = TRUE)
rownames(data) <- c("Ikut Bimbel", "Tidak Bimbel")
colnames(data) <- c("Lolos PTN", "Tidak Lolos")
# Tampilkan dengan total
addmargins(data)
#> Lolos PTN Tidak Lolos Sum
#> Ikut Bimbel 60 40 100
#> Tidak Bimbel 20 80 100
#> Sum 80 120 200
n <- sum(data)
cat("Joint Distribution:\n")
#> Joint Distribution:
round(data / n, 4)
#> Lolos PTN Tidak Lolos
#> Ikut Bimbel 0.3 0.2
#> Tidak Bimbel 0.1 0.4
cat("\nMarginal — Baris:\n")
#>
#> Marginal — Baris:
round(rowSums(data / n), 4)
#> Ikut Bimbel Tidak Bimbel
#> 0.5 0.5
cat("\nMarginal — Kolom:\n")
#>
#> Marginal — Kolom:
round(colSums(data / n), 4)
#> Lolos PTN Tidak Lolos
#> 0.4 0.6
cat("\nConditional Probability P(Lolos PTN | Status Bimbel):\n")
#>
#> Conditional Probability P(Lolos PTN | Status Bimbel):
round(prop.table(data, margin = 1), 4)
#> Lolos PTN Tidak Lolos
#> Ikut Bimbel 0.6 0.4
#> Tidak Bimbel 0.2 0.8
a <- data[1, 1]; b <- data[1, 2]
c <- data[2, 1]; d <- data[2, 2]
odds_bimbel <- a / b
odds_tdk_bimbel <- c / d
OR <- (a * d) / (b * c)
RR <- (a / (a + b)) / (c / (c + d))
SE_ln_OR <- sqrt(1/a + 1/b + 1/c + 1/d)
CI_lower <- exp(log(OR) - 1.96 * SE_ln_OR)
CI_upper <- exp(log(OR) + 1.96 * SE_ln_OR)
cat(sprintf("Odds ikut bimbel = %.4f\n", odds_bimbel))
#> Odds ikut bimbel = 1.5000
cat(sprintf("Odds tidak bimbel = %.4f\n", odds_tdk_bimbel))
#> Odds tidak bimbel = 0.2500
cat(sprintf("Odds Ratio (OR) = %.4f\n", OR))
#> Odds Ratio (OR) = 6.0000
cat(sprintf("Relative Risk(RR) = %.4f\n", RR))
#> Relative Risk(RR) = 3.0000
cat(sprintf("95%% CI untuk OR = (%.4f ; %.4f)\n", CI_lower, CI_upper))
#> 95% CI untuk OR = (3.1873 ; 11.2948)
epitoolsif (!require(epitools, quietly = TRUE))
install.packages("epitools", repos = "https://cran.r-project.org")
library(epitools)
or_result <- oddsratio(data, method = "wald")
or_result$measure
#> NA
#> odds ratio with 95% C.I. estimate lower upper
#> Ikut Bimbel 1 NA NA
#> Tidak Bimbel 6 3.187331 11.29472
chi_result <- chisq.test(data, correct = FALSE)
print(chi_result)
#>
#> Pearson's Chi-squared test
#>
#> data: data
#> X-squared = 33.333, df = 1, p-value = 7.764e-09
cat("\nFrekuensi yang Diharapkan:\n")
#>
#> Frekuensi yang Diharapkan:
round(chi_result$expected, 2)
#> Lolos PTN Tidak Lolos
#> Ikut Bimbel 40 60
#> Tidak Bimbel 40 60
cat(sprintf("\nX-squared = %.4f, df = %d, p-value = %.6f\n",
chi_result$statistic, chi_result$parameter, chi_result$p.value))
#>
#> X-squared = 33.3333, df = 1, p-value = 0.000000
par(mfrow = c(1, 2), bg = "#fafafa",
family = "sans", col.main = "#1a1a2e",
col.lab = "#3d3d5c", col.axis = "#6b6b8a")
# Barplot proporsi bersyarat
prop_data <- prop.table(data, margin = 1)
barplot(t(prop_data),
beside = TRUE,
col = c("#2c5282", "#a0aec0"),
border = NA,
main = "Proporsi Lolos PTN berdasarkan Keikutsertaan Bimbel",
ylab = "Proporsi",
xlab = "",
ylim = c(0, 0.85),
cex.main = .93, cex.axis = .85)
legend("topright",
legend = colnames(data),
fill = c("#2c5282", "#a0aec0"),
border = NA, bty = "n", cex = .85)
abline(h = seq(0, 0.8, .2), col = "#e4e4ed", lwd = .6)
# Mosaic plot
mosaicplot(data,
color = c("#2c5282", "#a0aec0"),
border = "white",
main = "Mosaic Plot: Bimbel vs Lolos PTN",
xlab = "Status Bimbel",
ylab = "Status Kelulusan PTN",
cex.axis = .85)
par(mfrow = c(1, 1))
Uji Chi-Square. Nilai \(\chi^2 = 33{,}33\) dengan \(df = 1\) dan \(p < 0{,}001\). Karena \(p < 0{,}05\), \(H_0\) ditolak maka ada hubungan yang signifikan secara statistik antara keikutsertaan bimbel dan kelulusan PTN.
Odds Ratio. \(OR = 6{,}0\) dengan \(95\%\, CI: (3{,}19\,;\,11{,}30)\). Karena interval kepercayaannya tidak melewati angka 1, OR ini signifikan dan menunjukkan asosiasi yang kuat.
Relative Risk. \(RR = 3{,}0\) risiko lolos PTN pada siswa yang ikut bimbel tiga kali lebih besar dibanding yang tidak ikut bimbel.
Kekuatan asosiasi. Siswa yang ikut bimbel punya odds lolos PTN 6 kali lebih tinggi daripada siswa yang tidak ikut bimbel. Ini tergolong asosiasi yang kuat.
Risiko relatif. Secara lebih langsung, siswa yang ikut bimbel 3 kali lebih mungkin lolos PTN.
Probabilitas bersyarat. Dari 100 siswa yang ikut bimbel, 60 orang (60%) berhasil lolos PTN jauh lebih tinggi dibanding hanya 20 dari 100 siswa yang tidak ikut bimbel (20%).
Implikasi. Hasil ini menunjukkan bahwa keikutsertaan bimbel berkaitan erat dengan peluang lolos seleksi masuk PTN. Namun perlu diperhatikan bahwa hubungan ini bersifat asosiasi, bukan kausalitas faktor lain seperti kemampuan awal siswa, intensitas belajar mandiri, dan kualitas bimbel turut berperan.
Tugas ini membahas inferensi pada tabel kontingensi dua arah menggunakan dua kasus berbeda. Kasus 1 menggunakan tabel \(2 \times 2\) untuk menganalisis hubungan antara kebiasaan Kecanduan Alkohol dan Kanker Hati. Kasus 2 menggunakan tabel \(2 \times 3\) untuk menelaah hubungan antara gender dan identifikasi partai politik.
Setiap kasus mencakup penyusunan tabel, estimasi titik dan interval kepercayaan, berbagai pengujian hipotesis, serta interpretasi substantif dari hasil yang diperoleh.
# Paket yang digunakan
library(epitools)
library(vcd)
library(DescTools)
library(knitr)
library(kableExtra)
Data berikut menggambarkan hubungan antara kebiasaan Kecanduan Alkohol dan Kanker Hati dari studi case-control dengan total 1418 subjek.
# Input data
tbl1 <- matrix(c(688, 650, 21, 59),
nrow = 2, byrow = TRUE,
dimnames = list(
"Status Kecanduan Alkohol" = c("Alcoholic", "Non-Alcoholic"),
"Kanker Hati" = c("Cancer (+)", "Control (-)")
))
# Tabel dengan margin total
kable(addmargins(tbl1),
caption = "Tabel Kontingensi: Kecanduan Alkohol vs Kanker Hati") |>
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)
| Cancer (+) | Control (-) | Sum | |
|---|---|---|---|
| Alcoholic | 688 | 650 | 1338 |
| Non-Alcoholic | 21 | 59 | 80 |
| Sum | 709 | 709 | 1418 |
Dari tabel diperoleh: \(a = 688\), \(b = 650\), \(c = 21\), \(d = 59\), \(n = 1418\).
Proporsi kejadian Kanker Hati pada masing-masing kelompok dihitung sebagai:
\[\hat{p}_1 = \frac{a}{a+b} = \frac{688}{1338} \qquad \hat{p}_2 = \frac{c}{c+d} = \frac{21}{80}\]
a <- tbl1[1,1]; b <- tbl1[1,2]
c <- tbl1[2,1]; d <- tbl1[2,2]
n1 <- a + b; n2 <- c + d; n <- n1 + n2
p1 <- a / n1 # proporsi kanker pada Alcoholic
p2 <- c / n2 # proporsi kanker pada Non-Alcoholic
cat(sprintf("Proporsi kanker pada Alcoholic : %.4f (%.2f%%)\n", p1, p1*100))
#> Proporsi kanker pada Alcoholic : 0.5142 (51.42%)
cat(sprintf("Proporsi kanker pada Non-Alcoholic : %.4f (%.2f%%)\n", p2, p2*100))
#> Proporsi kanker pada Non-Alcoholic : 0.2625 (26.25%)
Menggunakan metode Wald (normal approximation):
\[CI_{95\%}: \quad \hat{p} \pm 1{,}96 \sqrt{\frac{\hat{p}(1-\hat{p})}{n}}\]
z <- qnorm(0.975)
# CI untuk p1
se_p1 <- sqrt(p1*(1-p1)/n1)
ci_p1 <- c(p1 - z*se_p1, p1 + z*se_p1)
# CI untuk p2
se_p2 <- sqrt(p2*(1-p2)/n2)
ci_p2 <- c(p2 - z*se_p2, p2 + z*se_p2)
cat(sprintf("CI 95%% Alcoholic : (%.4f ; %.4f)\n", ci_p1[1], ci_p1[2]))
#> CI 95% Alcoholic : (0.4874 ; 0.5410)
cat(sprintf("CI 95%% Non-Alcoholic : (%.4f ; %.4f)\n", ci_p2[1], ci_p2[2]))
#> CI 95% Non-Alcoholic : (0.1661 ; 0.3589)
\[RD = \hat{p}_1 - \hat{p}_2 \qquad SE_{RD} = \sqrt{\frac{\hat{p}_1(1-\hat{p}_1)}{n_1} + \frac{\hat{p}_2(1-\hat{p}_2)}{n_2}}\]
RD <- p1 - p2
se_RD <- sqrt(p1*(1-p1)/n1 + p2*(1-p2)/n2)
ci_RD <- c(RD - z*se_RD, RD + z*se_RD)
cat(sprintf("Risk Difference (RD) = %.4f\n", RD))
#> Risk Difference (RD) = 0.2517
cat(sprintf("95%% CI untuk RD = (%.4f ; %.4f)\n", ci_RD[1], ci_RD[2]))
#> 95% CI untuk RD = (0.1516 ; 0.3518)
\[RR = \frac{\hat{p}_1}{\hat{p}_2} \qquad SE_{\ln RR} = \sqrt{\frac{1-\hat{p}_1}{a} + \frac{1-\hat{p}_2}{c}}\]
RR <- p1 / p2
se_lnRR <- sqrt((1-p1)/a + (1-p2)/c)
ci_RR <- exp(log(RR) + c(-1,1) * z * se_lnRR)
cat(sprintf("Relative Risk (RR) = %.4f\n", RR))
#> Relative Risk (RR) = 1.9589
cat(sprintf("95%% CI untuk RR = (%.4f ; %.4f)\n", ci_RR[1], ci_RR[2]))
#> 95% CI untuk RR = (1.3517 ; 2.8387)
\[OR = \frac{ad}{bc} \qquad SE_{\ln OR} = \sqrt{\frac{1}{a}+\frac{1}{b}+\frac{1}{c}+\frac{1}{d}}\]
OR <- (a*d)/(b*c)
se_lnOR <- sqrt(1/a + 1/b + 1/c + 1/d)
ci_OR <- exp(log(OR) + c(-1,1) * z * se_lnOR)
cat(sprintf("Odds Ratio (OR) = %.4f\n", OR))
#> Odds Ratio (OR) = 2.9738
cat(sprintf("95%% CI untuk OR = (%.4f ; %.4f)\n", ci_OR[1], ci_OR[2]))
#> 95% CI untuk OR = (1.7867 ; 4.9494)
ringkasan <- data.frame(
Ukuran = c("p Alcoholic", "p Non-Alcoholic", "RD", "RR", "OR"),
Estimasi = round(c(p1, p2, RD, RR, OR), 4),
"Batas Bawah"= round(c(ci_p1[1], ci_p2[1], ci_RD[1], ci_RR[1], ci_OR[1]), 4),
"Batas Atas" = round(c(ci_p1[2], ci_p2[2], ci_RD[2], ci_RR[2], ci_OR[2]), 4)
)
kable(ringkasan,
col.names = c("Ukuran", "Estimasi Titik", "Batas Bawah (95%)", "Batas Atas (95%)"),
caption = "Ringkasan Estimasi Titik dan Interval Kepercayaan 95%") |>
kable_styling(bootstrap_options = c("striped","hover","condensed"), full_width = FALSE)
| Ukuran | Estimasi Titik | Batas Bawah (95%) | Batas Atas (95%) |
|---|---|---|---|
| p Alcoholic | 0.5142 | 0.4874 | 0.5410 |
| p Non-Alcoholic | 0.2625 | 0.1661 | 0.3589 |
| RD | 0.2517 | 0.1516 | 0.3518 |
| RR | 1.9589 | 1.3517 | 2.8387 |
| OR | 2.9738 | 1.7867 | 4.9494 |
Hipotesis: \(H_0: p_1 = p_2\) (proporsi kanker sama pada Alcoholic dan Non-Alcoholic) \(H_1: p_1 \neq p_2\)
Statistik uji menggunakan proporsi gabungan \(\hat{p} = (a+c)/n\):
\[Z = \frac{\hat{p}_1 - \hat{p}_2}{\sqrt{\hat{p}(1-\hat{p})\left(\frac{1}{n_1}+\frac{1}{n_2}\right)}}\]
uji_2p <- prop.test(x = c(a, c), n = c(n1, n2), correct = FALSE)
print(uji_2p)
#>
#> 2-sample test for equality of proportions without continuity correction
#>
#> data: c(a, c) out of c(n1, n2)
#> X-squared = 19.129, df = 1, p-value = 1.222e-05
#> alternative hypothesis: two.sided
#> 95 percent confidence interval:
#> 0.1516343 0.3517663
#> sample estimates:
#> prop 1 prop 2
#> 0.5142003 0.2625000
cat(sprintf("\nStatistik uji (X²) = %.4f\n", uji_2p$statistic))
#>
#> Statistik uji (X²) = 19.1292
cat(sprintf("p-value = %.6f\n", uji_2p$p.value))
#> p-value = 0.000012
Hipotesis: \(H_0\): Status Kecanduan Alkohol dan kejadian Kanker Hati saling independen \(H_1\): Keduanya tidak independen
\[\chi^2 = \sum_{i,j} \frac{(O_{ij} - E_{ij})^2}{E_{ij}}, \quad df = (r-1)(c-1)\]
chi1 <- chisq.test(tbl1, correct = FALSE)
print(chi1)
#>
#> Pearson's Chi-squared test
#>
#> data: tbl1
#> X-squared = 19.129, df = 1, p-value = 1.222e-05
cat("\nFrekuensi yang Diharapkan:\n")
#>
#> Frekuensi yang Diharapkan:
round(chi1$expected, 2)
#> Kanker Hati
#> Status Kecanduan Alkohol Cancer (+) Control (-)
#> Alcoholic 669 669
#> Non-Alcoholic 40 40
cat(sprintf("\nχ² = %.4f, df = %d, p-value = %.6f\n",
chi1$statistic, chi1$parameter, chi1$p.value))
#>
#> χ² = 19.1292, df = 1, p-value = 0.000012
Uji \(G^2\) merupakan alternatif uji chi-square berbasis perbandingan log-likelihood:
\[G^2 = 2 \sum_{i,j} O_{ij} \ln\!\left(\frac{O_{ij}}{E_{ij}}\right)\]
# Hitung G² secara manual
O <- tbl1
E <- chi1$expected
G2 <- 2 * sum(O * log(O / E))
df_g2 <- (nrow(tbl1) - 1) * (ncol(tbl1) - 1)
pval_g2 <- pchisq(G2, df = df_g2, lower.tail = FALSE)
cat(sprintf("G² (Likelihood Ratio) = %.4f\n", G2))
#> G² (Likelihood Ratio) = 19.8780
cat(sprintf("df = %d\n", df_g2))
#> df = 1
cat(sprintf("p-value = %.6f\n", pval_g2))
#> p-value = 0.000008
# Verifikasi dengan GTest dari DescTools
GTest(tbl1)
#>
#> Log likelihood ratio (G-test) test of independence without correction
#>
#> data: tbl1
#> G = 19.878, X-squared df = 1, p-value = 8.254e-06
Fisher exact test digunakan saat asumsi chi-square (frekuensi harapan ≥ 5) tidak terpenuhi, atau untuk validasi tambahan pada tabel \(2 \times 2\).
fisher1 <- fisher.test(tbl1)
print(fisher1)
#>
#> Fisher's Exact Test for Count Data
#>
#> data: tbl1
#> p-value = 1.476e-05
#> alternative hypothesis: true odds ratio is not equal to 1
#> 95 percent confidence interval:
#> 1.755611 5.210711
#> sample estimates:
#> odds ratio
#> 2.971634
cat(sprintf("\nOR dari Fisher test = %.4f\n", fisher1$estimate))
#>
#> OR dari Fisher test = 2.9716
cat(sprintf("95%% CI = (%.4f ; %.4f)\n",
fisher1$conf.int[1], fisher1$conf.int[2]))
#> 95% CI = (1.7556 ; 5.2107)
cat(sprintf("p-value = %.6f\n", fisher1$p.value))
#> p-value = 0.000015
perbandingan <- data.frame(
Uji = c("Uji Dua Proporsi", "Chi-Square", "Likelihood Ratio (G²)", "Fisher Exact Test"),
Hipotesis_Nol = rep("p1 = p2 (independen)", 4),
Statistik_Uji = c(
sprintf("Z² = %.4f", uji_2p$statistic),
sprintf("χ² = %.4f", chi1$statistic),
sprintf("G² = %.4f", G2),
"— (exact)"
),
p_value = c(
sprintf("%.6f", uji_2p$p.value),
sprintf("%.6f", chi1$p.value),
sprintf("%.6f", pval_g2),
sprintf("%.6f", fisher1$p.value)
),
Keputusan = rep("Tolak H₀", 4)
)
kable(perbandingan,
col.names = c("Metode Uji", "Hipotesis Nol", "Statistik Uji", "p-value", "Keputusan"),
caption = "Perbandingan Empat Metode Uji Hipotesis") |>
kable_styling(bootstrap_options = c("striped","hover","condensed"), full_width = TRUE)
| Metode Uji | Hipotesis Nol | Statistik Uji | p-value | Keputusan |
|---|---|---|---|---|
| Uji Dua Proporsi | p1 = p2 (independen) | Z² = 19.1292 | 0.000012 | Tolak H₀ |
| Chi-Square | p1 = p2 (independen) | χ² = 19.1292 | 0.000012 | Tolak H₀ |
| Likelihood Ratio (G²) | p1 = p2 (independen) | G² = 19.8780 | 0.000008 | Tolak H₀ |
| Fisher Exact Test | p1 = p2 (independen) | — (exact) | 0.000015 | Tolak H₀ |
Keempat uji menghasilkan keputusan yang sama: tolak \(H_0\). Semua nilai \(p\) jauh di bawah \(\alpha = 0{,}05\), yang berarti ada hubungan yang signifikan antara Kecanduan Alkohol dan Kanker Hati.
Perbedaan utama keempat uji:
par(mfrow = c(1, 2), bg = "#fafafa",
family = "sans", col.main = "#1a1a2e", col.lab = "#3d3d5c")
# Barplot proporsi bersyarat
prop1 <- prop.table(tbl1, margin = 1)
barplot(t(prop1),
beside = TRUE,
col = c("#2c5282", "#a0aec0"),
border = NA,
main = "Proporsi Kanker per Kelompok",
ylab = "Proporsi",
ylim = c(0, 0.9),
cex.main = .93, cex.axis = .85)
legend("topright",
legend = colnames(tbl1),
fill = c("#2c5282","#a0aec0"),
border = NA, bty = "n", cex = .85)
abline(h = seq(0, 0.8, .2), col = "#e4e4ed", lwd = .5)
# Mosaic plot
mosaicplot(tbl1,
color = c("#2c5282","#a0aec0"),
border = "white",
main = "Mosaic Plot: Kecanduan Alkohol vs Kanker",
xlab = "Status Kecanduan Alkohol",
ylab = "Status Kanker",
cex.axis = .85)
par(mfrow = c(1,1))
#> Ringkasan Kasus 1:
#>
#> Proporsi kanker pada Alcoholic : 0.5142 (51.4%)
#>
#> Proporsi kanker pada Non-Alcoholic : 0.2625 (26.2%)
#>
#> Risk Difference (RD) : 0.2517 95% CI (0.1516 ; 0.3518)
#>
#> Relative Risk (RR) : 1.9589 95% CI (1.3517 ; 2.8387)
#>
#> Odds Ratio (OR) : 2.9738 95% CI (1.7867 ; 4.9494)
Berdasarkan keempat metode uji (dua proporsi, chi-square, likelihood ratio, dan Fisher exact), semuanya memberikan \(p < 0{,}001\) sehingga \(H_0\) ditolak. Terdapat hubungan yang signifikan secara statistik antara kebiasaan Kecanduan Alkohol dan kejadian Kanker Hati.
Dari sisi besar efek: Pecandu minuman keras punya peluang terkena Kanker Hati sebesar 51.4% dibanding 26.2% pada non-Pecandu minuman keras. Nilai \(RR = 1.96\) berarti Pecandu minuman keras 1.96 kali lebih mungkin terkena kanker. Nilai \(OR = 2.97\) menunjukkan asosiasi yang sangat kuat. Selisih risikonya (\(RD = 0.252\)) juga bermakna secara klinis. Interval kepercayaan untuk ketiga ukuran asosiasi tidak mencakup nilai netral (0 untuk RD, 1 untuk RR dan OR), memperkuat kesimpulan bahwa hubungan ini bukan kebetulan.
Data berikut menggambarkan hubungan antara gender dan identifikasi partai politik pada 2450 responden.
tbl2 <- matrix(c(495, 272, 590,
330, 265, 498),
nrow = 2, byrow = TRUE,
dimnames = list(
"Gender" = c("Female", "Male"),
"Partai" = c("Democrat", "Republican", "Independent")
))
kable(addmargins(tbl2),
caption = "Tabel Kontingensi: Gender vs Identifikasi Partai Politik") |>
kable_styling(bootstrap_options = c("striped","hover","condensed"),
full_width = FALSE)
| Democrat | Republican | Independent | Sum | |
|---|---|---|---|---|
| Female | 495 | 272 | 590 | 1357 |
| Male | 330 | 265 | 498 | 1093 |
| Sum | 825 | 537 | 1088 | 2450 |
Frekuensi harapan dihitung berdasarkan asumsi independensi:
\[E_{ij} = \frac{n_{i+} \times n_{+j}}{n}\]
chi2 <- chisq.test(tbl2, correct = FALSE)
kable(round(chi2$expected, 2),
caption = "Frekuensi yang Diharapkan ($E_{ij}$)") |>
kable_styling(bootstrap_options = c("striped","hover","condensed"),
full_width = FALSE)
| Democrat | Republican | Independent | |
|---|---|---|---|
| Female | 456.95 | 297.43 | 602.62 |
| Male | 368.05 | 239.57 | 485.38 |
# Cek asumsi: semua E_ij >= 5
cat("Semua nilai E_ij >= 5:", all(chi2$expected >= 5))
#> Semua nilai E_ij >= 5: TRUE
Semua frekuensi harapan ≥ 5, sehingga asumsi uji chi-square terpenuhi.
Hipotesis: \(H_0\): Gender dan identifikasi partai politik saling independen \(H_1\): Keduanya tidak independen
print(chi2)
#>
#> Pearson's Chi-squared test
#>
#> data: tbl2
#> X-squared = 12.569, df = 2, p-value = 0.001865
cat(sprintf("\nχ² = %.4f, df = %d, p-value = %.6f\n",
chi2$statistic, chi2$parameter, chi2$p.value))
#>
#> χ² = 12.5693, df = 2, p-value = 0.001865
Residual Pearson mengukur penyimpangan relatif tiap sel dari ekspektasinya:
\[r_{ij} = \frac{O_{ij} - E_{ij}}{\sqrt{E_{ij}}}\]
Standardized residual (residual terstandarisasi) memperhitungkan variabilitas sel dan dapat diinterpretasikan seperti skor-\(z\):
\[d_{ij} = \frac{O_{ij} - E_{ij}}{\sqrt{E_{ij}(1 - \hat{p}_{i+})(1 - \hat{p}_{+j})}}\]
# Residual Pearson
res_pearson <- chi2$residuals
cat("=== Residual Pearson ===\n")
#> === Residual Pearson ===
round(res_pearson, 4)
#> Partai
#> Gender Democrat Republican Independent
#> Female 1.7801 -1.4747 -0.5140
#> Male -1.9834 1.6431 0.5728
# Standardized residual
res_std <- chi2$stdres
cat("\n=== Standardized Residual ===\n")
#>
#> === Standardized Residual ===
round(res_std, 4)
#> Partai
#> Gender Democrat Republican Independent
#> Female 3.2724 -2.4986 -1.0322
#> Male -3.2724 2.4986 1.0322
# Sajikan berdampingan
tbl_res <- rbind(
round(res_pearson, 3),
round(res_std, 3)
)
rownames(tbl_res) <- c("Residual Pearson — Female",
"Residual Pearson — Male",
"Std. Residual — Female",
"Std. Residual — Male")
# rapikan
kable(
data.frame(
Kelompok = c("Female","Male","Female","Male"),
Jenis = c("Pearson","Pearson","Standardized","Standardized"),
Democrat = c(res_pearson[1,1], res_pearson[2,1],
res_std[1,1], res_std[2,1]),
Republican = c(res_pearson[1,2], res_pearson[2,2],
res_std[1,2], res_std[2,2]),
Independent= c(res_pearson[1,3], res_pearson[2,3],
res_std[1,3], res_std[2,3])
) |> (\(x){ x[,3:5] <- round(x[,3:5],3); x })(),
caption = "Residual Pearson dan Standardized Residual"
) |>
kable_styling(bootstrap_options = c("striped","hover","condensed"),
full_width = FALSE)
| Kelompok | Jenis | Democrat | Republican | Independent |
|---|---|---|---|---|
| Female | Pearson | 1.780 | -1.475 | -0.514 |
| Male | Pearson | -1.983 | 1.643 | 0.573 |
| Female | Standardized | 3.272 | -2.499 | -1.032 |
| Male | Standardized | -3.272 | 2.499 | 1.032 |
Standardized residual \(|d_{ij}| > 2\) mengindikasikan sel tersebut berkontribusi signifikan terhadap chi-square keseluruhan.
Chi-square keseluruhan (\(df = 2\)) dapat dipartisi menjadi dua komponen \(df = 1\) yang saling ortogonal.
# Subset: hanya Democrat dan Republican
tbl2_dr <- tbl2[, c("Democrat", "Republican")]
chi2_dr <- chisq.test(tbl2_dr, correct = FALSE)
cat("=== Partisi 1: Democrat vs Republican ===\n")
#> === Partisi 1: Democrat vs Republican ===
print(chi2_dr)
#>
#> Pearson's Chi-squared test
#>
#> data: tbl2_dr
#> X-squared = 11.555, df = 1, p-value = 0.0006758
cat(sprintf("χ²₁ = %.4f, df = %d, p = %.6f\n",
chi2_dr$statistic, chi2_dr$parameter, chi2_dr$p.value))
#> χ²₁ = 11.5545, df = 1, p = 0.000676
# Gabungkan Democrat dan Republican
tbl2_di <- cbind(
"Dem+Rep" = rowSums(tbl2[, c("Democrat","Republican")]),
"Independent" = tbl2[, "Independent"]
)
chi2_di <- chisq.test(tbl2_di, correct = FALSE)
cat("=== Partisi 2: (Democrat + Republican) vs Independent ===\n")
#> === Partisi 2: (Democrat + Republican) vs Independent ===
print(chi2_di)
#>
#> Pearson's Chi-squared test
#>
#> data: tbl2_di
#> X-squared = 1.0654, df = 1, p-value = 0.302
cat(sprintf("χ²₂ = %.4f, df = %d, p = %.6f\n",
chi2_di$statistic, chi2_di$parameter, chi2_di$p.value))
#> χ²₂ = 1.0654, df = 1, p = 0.301979
# Verifikasi aditivitas chi-square
chi2_total <- chi2$statistic
chi2_part1 <- chi2_dr$statistic
chi2_part2 <- chi2_di$statistic
chi2_sum <- chi2_part1 + chi2_part2
tbl_partisi <- data.frame(
Komponen = c("Keseluruhan (2×3)",
"Partisi 1: Dem vs Rep",
"Partisi 2: (Dem+Rep) vs Ind",
"Jumlah Partisi 1 + 2"),
Chi_Square = round(c(chi2_total, chi2_part1, chi2_part2, chi2_sum), 4),
df = c(2, 1, 1, 2),
p_value = round(c(chi2$p.value, chi2_dr$p.value,
chi2_di$p.value, NA), 6)
)
kable(tbl_partisi,
col.names = c("Komponen", "χ²", "df", "p-value"),
caption = "Perbandingan Chi-Square Keseluruhan dan Partisi") |>
kable_styling(bootstrap_options = c("striped","hover","condensed"),
full_width = FALSE)
| Komponen | χ² | df | p-value |
|---|---|---|---|
| Keseluruhan (2×3) | 12.5693 | 2 | 0.001865 |
| Partisi 1: Dem vs Rep | 11.5545 | 1 | 0.000676 |
| Partisi 2: (Dem+Rep) vs Ind | 1.0654 | 1 | 0.301979 |
| Jumlah Partisi 1 + 2 | 12.6200 | 2 | NA |
cat(sprintf("\nVerifikasi aditivitas: %.4f + %.4f = %.4f (total = %.4f)\n",
chi2_part1, chi2_part2, chi2_sum, chi2_total))
#>
#> Verifikasi aditivitas: 11.5545 + 1.0654 = 12.6200 (total = 12.5693)
Sifat aditivitas chi-square terpenuhi bila jumlah nilai \(\chi^2\) dari dua partisi mendekati \(\chi^2\) keseluruhan.
par(mfrow = c(2, 2), bg = "#fafafa",
family = "sans", col.main = "#1a1a2e", col.lab = "#3d3d5c")
# 1. Barplot proporsi bersyarat
prop2 <- prop.table(tbl2, margin = 1)
barplot(t(prop2),
beside = TRUE,
col = c("#2c5282","#718096","#a0aec0"),
border = NA,
main = "Proporsi Partai per Gender",
ylab = "Proporsi",
ylim = c(0, 0.65),
cex.main = .9, cex.axis = .8)
legend("topright",
legend = colnames(tbl2),
fill = c("#2c5282","#718096","#a0aec0"),
border = NA, bty = "n", cex = .8)
abline(h = seq(0, 0.6, .1), col = "#e4e4ed", lwd = .5)
# 2. Mosaic plot
mosaicplot(tbl2,
color = c("#2c5282","#718096","#a0aec0"),
border = "white",
main = "Mosaic Plot: Gender vs Partai",
xlab = "Gender",
ylab = "Identifikasi Partai",
cex.axis = .8)
# 3. Plot standardized residual
std_res_long <- as.data.frame(as.table(round(res_std, 2)))
colnames(std_res_long) <- c("Gender","Partai","Residual")
cols_res <- ifelse(std_res_long$Residual > 0, "#2c5282", "#a0aec0")
bp <- barplot(std_res_long$Residual,
names.arg = paste(std_res_long$Gender, std_res_long$Partai, sep="\n"),
col = cols_res,
border = NA,
main = "Standardized Residual",
ylab = "Nilai Residual",
cex.names = .72,
cex.main = .9,
las = 2)
abline(h = c(-2, 0, 2), col = c("#e11d48","#475569","#e11d48"),
lty = c(2,1,2), lwd = c(1.2,0.8,1.2))
# 4. Barplot frekuensi observasi
barplot(t(tbl2),
beside = TRUE,
col = c("#2c5282","#718096","#a0aec0"),
border = NA,
main = "Frekuensi Observasi",
ylab = "Frekuensi",
cex.main = .9, cex.axis = .8)
legend("topright",
legend = colnames(tbl2),
fill = c("#2c5282","#718096","#a0aec0"),
border = NA, bty = "n", cex = .8)
par(mfrow = c(1,1))
# Kontribusi tiap sel terhadap chi-square total
kontribusi <- (tbl2 - chi2$expected)^2 / chi2$expected
kable(round(kontribusi, 4),
caption = "Kontribusi Tiap Sel terhadap χ² Total") |>
kable_styling(bootstrap_options = c("striped","hover","condensed"),
full_width = FALSE)
| Democrat | Republican | Independent | |
|---|---|---|---|
| Female | 3.1686 | 2.1746 | 0.2642 |
| Male | 3.9339 | 2.6999 | 0.3281 |
cat(sprintf("\nKontribusi terbesar: sel (%.0f, %.0f) = %.4f\n",
which(kontribusi == max(kontribusi), arr.ind=TRUE)[1],
which(kontribusi == max(kontribusi), arr.ind=TRUE)[2],
max(kontribusi)))
#>
#> Kontribusi terbesar: sel (2, 1) = 3.9339
# Proporsi kontribusi
cat("\nProporsi kontribusi terhadap total χ²:\n")
#>
#> Proporsi kontribusi terhadap total χ²:
round(kontribusi / chi2$statistic * 100, 2)
#> Partai
#> Gender Democrat Republican Independent
#> Female 25.21 17.30 2.10
#> Male 31.30 21.48 2.61
Berdasarkan analisis pada tabel \(2 \times 3\):
Uji keseluruhan: \(\chi^2 = 12.5693\) dengan \(df = 2\) dan \(p =0.001865\) — \(H_0\) ditolak. Ada hubungan yang signifikan antara gender dan identifikasi partai politik.
Residual: Standardized residual menunjukkan bahwa sel yang paling menyimpang dari ekspektasinya adalah Female–Democrat (positif, artinya perempuan lebih banyak memilih Democrat dari yang diharapkan) dan Male–Democrat (negatif, artinya laki-laki lebih sedikit memilih Democrat dari yang diharapkan).
Partisi chi-square:
Dengan demikian, perbedaan gender paling terasa pada preferensi Democrat vs Republican, di mana perempuan cenderung lebih ke Democrat dan laki-laki cenderung lebih ke Republican.