본문 바로가기

Theory/Statistics

파이썬으로 보는 통계 (4) - 카이제곱 검정

반응형

카이제곱 검정은 교차분석이라고도 불리며, 두 범주형 변수 $A, B$가 서로 종속사건인지 독립사건인지 판별하는 것으로 각 범주형 변수에서 관찰된 빈도와 기대 빈도와 얼마나 다른지를 검증합니다. 종속사건이란 사건 $A$가 발생 후 사건 $B$가 발생할 확률과 ($P(B|A)$) 사건 $B$가 발생할 확률이 ($P(B)$) 다른 경우로 두 개의 사건이 독립적이지 않고 어떠한 형태로 연관되어 있는 사건을 말합니다.

카이제곱 검정에 사용하는 카이제곱 검정통계량은 데이터 분포와 가정된 분포 사이의 차이를 나타내는 측정값으로 가정된 분포란 귀무가설일 경우의 분포를 말합니다. 카이제곱 검정에서의 귀무가설은 두 범주형 변수가 독립 사건이다 라고 가정한 것으로 카이제곱 통계량은 다음과 같이 정의됩니다.

$\chi^2 = \sum_{i=1}^k \frac{(O_i -E_i)^2}{E_i}$

$k$는 범주의 개수이고 $O_i, E_i$는 각각 관측 빈도와 기대 빈도입니다. 이때 각 변수의 범주의 개수가 각각 $k_1, k_2$라면 $\chi^2$는 자유도가 $(k_1-1)(k_2-1)$인 카이제곱 분포를 따르게 됩니다.

In python

비만과 당뇨가 상관관계를 분석하기 위해 다음과 같은 관측 데이터가 있다고 가정합니다.

  당뇨 정상 전체
비만체중 10 10 20
정상체중 15 65 80
전체 25 75 100

 

만약 귀무가설이 맞다면, 비만과 당뇨가 서로 독립적이라면 기대 분포는 어떻게 되어야 할까요? 전체에서 당뇨와 정상인 비율이 25:75=1:3 이므로 당뇨:정상 비율이 비만체중, 정상체중 모두에서 1:3의 분포를 가져야 합니다. 각 원소의 기대빈도는 (행의 합계)*(열의 합계) / (전체 합계)로 구할 수 있습니다.

  당뇨 정상 전체
비만체중 5 15 20
정상체중 20 60 80
전체 25 75 100

 

이를 통해 카이제곱 통계량을 구해보면,

$(10-5)^2 / 5 + (10-15)^2 / 15 + (15-20)^2 / 20 + (65-60)^2 / 60 = 8.33$

으로 이 값을 자유도가 2-1 인 카이제곱 분포에 맞추어 p-value를 계산합니다. 카이제곱 분포는 양수인 확률변수에 대해 정의되므로 단측검정이 사용됩니다.

 

파이썬에서는 scipy.stats 모듈의 chi2_contingency 함수를 이용해 구할 수 있습니다. 데이터를 생성하고 chi2_contingency 함수를 통해 얻은 p-value로 두 범수형 변수의 독립 기각 여부를 판별할 수 있습니다.

import pandas as pd

obs = pd.DataFrame({'당뇨': [10,15], '정상': [10,65]})
obs.index = ['비만체중', '정상체중']

from scipy.stats import chi2_contingency

chiresult = chi2_contingency(obs, correction=False)
print('Chi square: {}'.format(chiresult[0]))
print('P-value: {}'.format(chiresult[1]))

chi2_contingency 함수의 correction 파라미터는 디폴트가 True로 설정되어 있습니다. correction 파라미터가 True이고 자유도가 1이라면 관측치는 0.5씩 기대값으로 옮기는 Yates' correction이 적용되어 검정통계량이 더 낮게 나오게 됩니다. 결과적으로 p-value가 0.05보다 낮으므로 귀무가설을 기각하여 두 변수가 독립이 아니라고 판단할 수 있습니다.


위의 경우는 카이제곱 검정의 독립성 검정이고 어떠한 관측값이 어떤 이론이나 이론적 분포를 따르고 있는지 검사하는 적합도 검정에도 사용할 수 있습니다. 예를 들어 어느 회사에서 3교대 근무를 하고 각 교대조마다 1일의 결점수를 조사했을 때, 결점수가 각 조에 의해서 차이가 있다고 말할 수 있는지 알고 싶습니다.

  1조 2조 3조 총합
관측 결점수 23 18 37 78
기대 결점수 26 26 26 78

 

이러한 경우에도 마찬가지로 카이제곱 검정을 이용하여 판단할 수 있습니다. scipy.stats 모듈의 chisquare 함수에 관측 데이터와 기대 데이터를 넣으면 p-value를 얻을 수 있습니다.

import pandas as pd

xo, xe = [26,26,26,], [23, 18, 37]
xc = pd.DataFrame([xo, xe], columns=['1조', '2조', '3조'], index=['Obs', 'Exp'])

from scipy.stats import chisquare

chiresult = chisquare(xo, xe)
print('Chi square: {}'.format(chiresult[0]))
print('P-value: {}'.format(chiresult[1]))

P-value 결과를 볼때 유의수준 0.05에서 교대조에 의한 결점수는 차이가 있다고 판단할 수 있습니다.

반응형