Lewati ke konten utama

Tutorial Tabel Kontingensi R

Dalam tutorial ini, Anda akan belajar cara membuat tabel kontingensi serta cara menguji dan mengkuantifikasi hubungan yang terlihat di dalamnya.
· 10 mnt Baca

Jelajahi bersama AI

Cara Membuat Tabel

Pertama, mari ambil beberapa data. Paket MASS berisi data tentang 93 mobil yang dijual di AS pada tahun 1993. Data tersebut disimpan dalam objek Cars93 dan mencakup 27 fitur untuk setiap mobil, beberapa di antaranya bersifat kategorikal. Jadi mari muat paket MASS dan lihat jenis kendaraan yang termasuk dalam cars93:

library(MASS)
Cars93$Type

##  [1] Small   Midsize Compact Midsize Midsize Midsize Large   Large  
##  [9] Midsize Large   Midsize Compact Compact Sporty  Midsize Van    
## [17] Van     Large   Sporty  Large   Compact Large   Small   Small  
## [25] Compact Van     Midsize Sporty  Small   Large   Small   Small  
## [33] Compact Sporty  Sporty  Van     Midsize Large   Small   Sporty
## [41] Sporty  Small   Compact Small   Small   Sporty  Midsize Midsize
## [49] Midsize Midsize Midsize Large   Small   Small   Compact Van    
## [57] Sporty  Compact Midsize Sporty  Midsize Small   Midsize Small  
## [65] Compact Van     Midsize Compact Midsize Van     Large   Sporty
## [73] Small   Compact Sporty  Midsize Large   Compact Small   Small  
## [81] Small   Compact Small   Small   Sporty  Midsize Van     Small  
## [89] Van     Compact Sporty  Compact Midsize
## Levels: Compact Large Midsize Small Sporty Van

Kita memiliki 6 jenis mobil di sana. Fungsi table memberi tahu berapa banyak dari setiap jenis yang kita punya:

table(Cars93$Type)

##
## Compact   Large Midsize   Small  Sporty     Van
##      16      11      22      21      14       9

prop.table mengonversinya menjadi pecahan:

prop.table(table(Cars93$Type))

##
##    Compact      Large    Midsize      Small     Sporty        Van
## 0.17204301 0.11827957 0.23655914 0.22580645 0.15053763 0.09677419

Sama halnya dengan asal mobil:

table(Cars93$Origin)

##
##     USA non-USA
##      48      45

prop.table(table(Cars93$Origin))

##
##      USA  non-USA
## 0.516129 0.483871

Cara Membuat Tabel Kontingensi

Bagus, kita melihat bahwa dataset kita berisi jumlah mobil AS dan non-AS yang serupa dan bahwa jenis yang paling banyak adalah Midsize dan Small. Namun, mungkin saja AS dan non-AS berbeda dalam hal jenis?

Mari lihat jenis mobil berdasarkan asalnya. Kita bisa menggunakan table lagi, namun sekarang dengan dua argumen. Argumen pertama akan menjadi variabel baris dan yang kedua menjadi variabel kolom:

table(Cars93$Type, Cars93$Origin)

##          
##           USA non-USA
##   Compact   7       9
##   Large    11       0
##   Midsize  10      12
##   Small     7      14
##   Sporty    8       6
##   Van       5       4

Sekarang, kita melihat apa yang sudah diketahui semua orang: orang Amerika menyukai kendaraan besar! Tabel di atas menunjukkan distribusi gabungan dari dua variabel kategorikal (Type dan Origin). Tabel seperti ini disebut tabel kontingensi.

Cara Mendapatkan Marginal dari Tabel Kontingensi

Fungsi rowSums dan colSums sangat jelas kegunaannya

(tab1<-table(Cars93$Type, Cars93$Origin))

##          
##           USA non-USA
##   Compact   7       9
##   Large    11       0
##   Midsize  10      12
##   Small     7      14
##   Sporty    8       6
##   Van       5       4

rowSums(tab1)

## Compact   Large Midsize   Small  Sporty     Van
##      16      11      22      21      14       9

colSums(tab1)

##     USA non-USA
##      48      45

Cara Mendapatkan Persentase dari Tabel Kontingensi

prop.table yang digabung dengan table memberikan frekuensi

prop.table(table(Cars93$Type, Cars93$Origin))

##          
##                  USA    non-USA
##   Compact 0.07526882 0.09677419
##   Large   0.11827957 0.00000000
##   Midsize 0.10752688 0.12903226
##   Small   0.07526882 0.15053763
##   Sporty  0.08602151 0.06451613
##   Van     0.05376344 0.04301075

Konversi ke persentase hanya dengan mengalikan 100:

prop.table(table(Cars93$Type, Cars93$Origin))*100

##          
##                 USA   non-USA
##   Compact  7.526882  9.677419
##   Large   11.827957  0.000000
##   Midsize 10.752688 12.903226
##   Small    7.526882 15.053763
##   Sporty   8.602151  6.451613
##   Van      5.376344  4.301075

Perhatikan, bahwa ini adalah distribusi probabilitas gabungan, dari mana kita dapat melihat bahwa misalnya, sekitar 7,5% mobil berukuran kecil dan berasal dari Amerika.

Lebih sering, kita tertarik pada distribusi satu variabel dalam kelompok yang dibentuk oleh variabel lain. Di sini, distribusi jenis mobil di antara mobil AS dan (secara terpisah) non-AS tampak menarik. Untuk mendapatkannya, kita menggunakan argumen margin pada fungsi prop.table. Argumen ini memberi tahu di mana variabel pengelompokan berada: di baris (margin=1) atau di kolom (margin=2):

prop.table(table(Cars93$Type, Cars93$Origin), margin=2)*100

##          
##                 USA   non-USA
##   Compact 14.583333 20.000000
##   Large   22.916667  0.000000
##   Midsize 20.833333 26.666667
##   Small   14.583333 31.111111
##   Sporty  16.666667 13.333333
##   Van     10.416667  8.888889

Sekarang kita bisa dengan mudah melihat bahwa mobil kecil dua kali lebih sering muncul pada bagian non-AS dibandingkan AS dalam dataset kita.

Juga perhatikan bahwa persentase dijumlahkan menjadi 100 pada kolom, sedangkan pada tabel distribusi gabungan (yang tanpa argumen margin), 100 merupakan jumlah seluruh tabel.

(tab2<-prop.table(table(Cars93$Type, Cars93$Origin), margin=2)*100)

##          
##                 USA   non-USA
##   Compact 14.583333 20.000000
##   Large   22.916667  0.000000
##   Midsize 20.833333 26.666667
##   Small   14.583333 31.111111
##   Sporty  16.666667 13.333333
##   Van     10.416667  8.888889

colSums(tab2)

##     USA non-USA
##     100     100

Uji Chi-kuadrat

Pertanyaan paling umum yang muncul dari tabel kontingensi adalah apakah variabel baris dan kolom saling independen. Cara paling dasar untuk menjawabnya adalah menjalankan uji chi-kuadrat. Hal ini dibahas secara rinci dalam tutorial ini. Mari periksa apakah Type dan Origin independen:

chisq.test(Cars93$Type, Cars93$Origin)

## Warning in chisq.test(Cars93$Type, Cars93$Origin): Chi-squared
## approximation may be incorrect

##
##  Pearson's Chi-squared test
##
## data:  Cars93$Type and Cars93$Origin
## X-squared = 14.08, df = 5, p-value = 0.01511

Ternyata, tidak, tetapi kita juga mendapatkan peringatan Chi-squared approximation may be incorrect. Ini karena statistik chi-kuadrat mengikuti distribusi chi-kuadrat hanya secara aproksimasi. Semakin banyak observasi yang kita miliki, semakin baik pendekatannya. Fungsi chisq.test menampilkan peringatan di atas setiap kali salah satu nilai harapan kurang dari 5 (untuk penjelasan apa itu "nilai harapan", lihat tutorial yang ditautkan di atas).

Uji Eksak Fisher

Uji eksak Fisher adalah alternatif dari uji chi-kuadrat yang digunakan terutama ketika pendekatan chi-kuadrat tidak memadai. Mari jalankan:

fisher.test(Cars93$Type, Cars93$Origin)

##
##  Fisher's Exact Test for Count Data
##
## data:  Cars93$Type and Cars93$Origin
## p-value = 0.007248
## alternative hypothesis: two.sided

Hasilnya cukup mirip dengan uji chi-kuadrat, tetapi tidak selalu demikian. Satu kelemahan besar uji eksak Fisher adalah untuk tabel besar (atau sampel besar) uji ini menjadi tidak efisien secara komputasi.

Uji G

Alternatif lain adalah apa yang disebut uji G. Statistiknya juga kira-kira berdistribusi chi-kuadrat, tetapi untuk sampel kecil, pendekatan ini lebih dekat daripada yang digunakan uji chi-kuadrat. Untuk uji G kita bisa menggunakan fungsi GTest dari paket DescTools. Hasilnya kembali cukup mirip dengan dua uji sebelumnya: Type dan Origin tidak independen.

library(DescTools)
GTest(Cars93$Type, Cars93$Origin)

##
##  Log likelihood ratio (G-test) test of independence without
##  correction
##
## data:  Cars93$Type and Cars93$Origin
## G = 18.362, X-squared df = 5, p-value = 0.002526

Koreksi Yates

Pada tabel kontingensi 2x2, uji chi-kuadrat dapat ditingkatkan dengan koreksi kontinuitas Yates. Koreksi ini cukup mengurangkan 0,5 dari setiap suku | Observed - Expected | pada statistik chi-kuadrat. Silakan merujuk kembali ke tutorial ini jika Anda merasa bingung sekarang. Selain itu, R menerapkan koreksi Yates secara otomatis kapan pun diperlukan. Mari lihat ketersediaan versi transmisi manual pada mobil AS dan non-AS:

(tab3<-table(Cars93$Man.trans.avail, Cars93$Origin))

##      
##       USA non-USA
##   No   26       6
##   Yes  22      39

chisq.test(tab3)

##
##  Pearson's Chi-squared test with Yates' continuity correction
##
## data:  tab3
## X-squared = 15.397, df = 1, p-value = 8.712e-05

Koreksi Yates diterapkan secara otomatis, dan R memberi tahu kita tentang hal itu.

Tabel 3 (atau lebih) Dimensi

Mari lihat Man.trans.avail, Origin, dan Type sekaligus. table membagi dataset menurut variabel yang disediakan sebagai variabel ketiga:

table(Cars93$Man.trans.avail, Cars93$Origin, Cars93$Type)

## , ,  = Compact
##
##      
##       USA non-USA
##   No    2       0
##   Yes   5       9
##
## , ,  = Large
##
##      
##       USA non-USA
##   No   11       0
##   Yes   0       0
##
## , ,  = Midsize
##
##      
##       USA non-USA
##   No    9       4
##   Yes   1       8
##
## , ,  = Small
##
##      
##       USA non-USA
##   No    0       0
##   Yes   7      14
##
## , ,  = Sporty
##
##      
##       USA non-USA
##   No    0       0
##   Yes   8       6
##
## , ,  = Van
##
##      
##       USA non-USA
##   No    4       2
##   Yes   1       2

ftable memberikan tampilan yang lebih ringkas:

ftable(Cars93$Man.trans.avail, Cars93$Origin, Cars93$Type)

##              Compact Large Midsize Small Sporty Van
##                                                    
## No  USA            2    11       9     0      0   4
##     non-USA        0     0       4     0      0   2
## Yes USA            5     0       1     7      8   1
##     non-USA        9     0       8    14      6   2

Uji Cochran-Mantel-Haenszel

Dari hasil table di atas, seharusnya jelas bahwa hubungan antara Origin dan Man.trans.avail berbeda menurut Type. Untuk mobil kecil dan sporty, misalnya, tidak ada asosiasi: setiap mobil kecil atau sporty baik dari AS maupun non-AS tersedia dalam versi manual. Di sisi lain, sebagian besar mobil AS berukuran menengah tidak memiliki versi manual, sementara sebagian besar mobil non-AS dari jenis ini memilikinya. Untuk memperhitungkan kemungkinan perbedaan hubungan antarkelompok (strata), uji Cochran-Mantel-Haenszel dapat digunakan:

mantelhaen.test(Cars93$Man.trans.avail, Cars93$Origin, Cars93$Type)

##
##  Mantel-Haenszel chi-squared test with continuity correction
##
## data:  Cars93$Man.trans.avail and Cars93$Origin and Cars93$Type
## Mantel-Haenszel X-squared = 8.0153, df = 1, p-value = 0.004638
## alternative hypothesis: true common odds ratio is not equal to 1
## 95 percent confidence interval:
##   2.226531 76.891307
## sample estimates:
## common odds ratio
##          13.08438

Argumen ketiga yang diberikan ke mantelhaen.test mengidentifikasi strata. Bandingkan hasil di atas dengan yang tanpa stratifikasi (contoh koreksi Yates di atas). Asosiasi masih ada, tetapi buktinya jauh lebih lemah.

Ukuran asosiasi

Setelah kita menemukan beberapa asosiasi antarvariabel, saatnya mengukur kekuatannya. Ada banyak sekali jenis ukuran yang memungkinkan. Banyak di antaranya dijelaskan di sini. Sekarang saya akan fokus pada dua yang paling banyak digunakan.

V Cramer

V didasarkan pada statistik chi-kuadrat:

$$ V = \sqrt{\frac{\chi^2/N}{\min(C-1, R-1)}}, $$ di mana:

  • N adalah total keseluruhan tabel kontingensi (jumlah semua selnya),
  • C adalah jumlah kolom
  • R adalah jumlah baris.

V ∈ [0; 1]. Semakin besar V, semakin kuat hubungan antara variabel. V = 0 dapat diinterpretasikan sebagai independen (karena V = 0 jika dan hanya jika χ2 = 0). Kelemahan utama V adalah kurangnya interpretasi yang tepat. Apakah V = 0,6 merupakan asosiasi yang kuat, sedang, atau lemah?

Fungsi CramerV dari DescTools dapat menghitungnya untuk kita:

CramerV(Cars93$Type, Cars93$Origin)

## [1] 0.3890967

Sekali lagi: apakah ini asosiasi yang kuat, sedang, atau lemah?

Lambda Goodman dan Kruskal

Lambda Goodman dan Kruskal adalah contoh ukuran yang didasarkan pada pengurangan proporsional dalam variasi. Ukuran-ukuran seperti ini bertujuan meniru R2 - koefisien determinasi dari regresi linear:

  • nilainya berada pada [0, 1]
  • menyatakan fraksi variasi yang dijelaskan oleh variabel independen.

Mari gunakan variabel kolom sebagai variabel independen. Rumus lambda Goodman dan Kruskal kemudian adalah: $$\lambda = \frac{L - \sum_j L_j}{L},$$ di mana:

  • Lj adalah jumlah frekuensi non-modal pada kolom ke-j,
  • L adalah jumlah frekuensi non-modal pada kolom "total"

Ini paling baik dijelaskan dengan contoh. Mari lihat Type dan Origin, yang terakhir sebagai independen:

table(Cars93$Type, Cars93$Origin)

##          
##           USA non-USA
##   Compact   7       9
##   Large    11       0
##   Midsize  10      12
##   Small     7      14
##   Sporty    8       6
##   Van       5       4

Modus kolom AS adalah 11, jadi L1 = 7 + 10 + 7 + 8 + 5 = 37. Modus kolom non-AS adalah 14, jadi L2 = 9 + 0 + 12 + 6 + 4 = 31. Kolom "Total" adalah

rowSums(table(Cars93$Type, Cars93$Origin))

## Compact   Large Midsize   Small  Sporty     Van
##      16      11      22      21      14       9

Modusnya adalah 22, jadi L = 16 + 11 + 21 + 14 + 9 = 71 dan $$\lambda = \frac{71 - (37+31)}{71}=0.042$$

Kita dapat menggunakan fungsi Lambda dari paket DescTools sebagai gantinya:

Lambda(Cars93$Type, Cars93$Origin, direction='row')

## [1] 0.04225352

Parameter direction menentukan di mana (di row atau di column) variabel dependen berada.

Origin hanya menjelaskan sekitar 4% variasi pada Type. Perhatikan dari rumus bahwa lambda mendefinisikan variasi sebagai dikotomi antara termasuk dan tidak termasuk dalam kelompok terbesar.

Perlu disebutkan bahwa lambda bernilai nol setiap kali kategori modal dari setiap kolom sama. Perhatikan tabel ini:

(lambdaTab<-cbind(c(0,100), c(49,51)))

##      [,1] [,2]
## [1,]    0   49
## [2,]  100   51

chisq.test(lambdaTab)

##
##  Pearson's Chi-squared test with Yates' continuity correction
##
## data:  lambdaTab
## X-squared = 62.279, df = 1, p-value = 2.981e-15

Kategori modal sama untuk setiap kolom (baris kedua). Jadi lambda harus nol meskipun terdapat asosiasi yang signifikan dan terlihat jelas:

Lambda(lambdaTab, direction='row')

## [1] 0

Jika Anda ingin mempelajari lebih lanjut tentang statistika di R, ikuti kursus Statistical Modeling in R (Bagian 1) dari DataCamp.

Topik

Terkait

blogs

Tutorial Korelasi di R

blogs

Spaghetti Plot dan Jalur Badai

blogs

40 Pertanyaan Wawancara DBMS Teratas di 2026