본문 바로가기
데이터분석과 AI/빅데이터 분석기사

[빅데이터분석기사 실기][작업형3]카이제곱 검정(적합도 검정, 독립성 검정)+피셔의 정확검정

by 우공80 2023. 6. 22.
728x90

카이제곱 검정, 피셔의 정확검정

카이 제곱 검정은 두 범주형 변수 사이에 유의미한 연관성이 있는지 확인하는 데 사용되는 통계 검정입니다. 분할표에서 관찰된 빈도를 변수가 독립적인 경우 예상되는 빈도와 비교합니다. 검정은 독립 가설을 평가할 수 있는 카이제곱 통계량과 p-값을 계산합니다.

다음은 Python에서 카이제곱 검정을 설명하는 예입니다.

 

1. 카이제곱 적합도 검정(일원 카이제곱검정)

카이제곱 적합도 검정은 관찰된 데이터가 특정 이론적 분포에 맞는지 확인하는 데 사용됩니다. 관찰된 빈도를 가설 분포를 기반으로 하는 예상 빈도와 비교합니다. 관측 빈도가 예상 빈도에서 크게 벗어나면 데이터가 가정된 분포를 따르지 않는다는 것을 나타냅니다.

 

아래는 알려진 혈액형 분포와 실제 관측치 간의 적합도를 검정하는 예제입니다.

 

H0(귀무가설): 관측치의 혈액형별 빈도가 알려진 혈액형별 빈도와 동일하다. 

H1(대립가설): 관측치의 혈액형별 빈도가 알려진 혈액형별 빈도와 다르다.

import numpy as np
import scipy.stats as stats

# 100명의 혈액형 데이터 생성
import random
# Create a list of blood types
blood_types = ['A'] * 30 + ['B'] * 25 + ['O'] * 27 + ['AB'] * 18
# Shuffle the list
random.shuffle(blood_types)
# Print the mixed up list
print(pd.Series(blood_types,name='BloodType'))

#알려진 혈액형 분포
expected=[34,27,27,12]

Output:아래와 같이 혈액형 데이터를 생성하였습니다.

0      A
1     AB
2      A
3      O
4      A
      ..
95    AB
96     A
97     O
98     A
99     A
Name: BloodType, Length: 100, dtype: object

카이제곱 검정은 범주별 빈도로 계산을 하므로 데이터를 범주의 빈도로 변경해주어야 합니다.

import numpy as np
import scipy.stats as stats

# 관찰빈도와 예상빈도의 분할표를 생성 
df2=pd.DataFrame({'Observed':[30,27,25,18],'Expected':[34,27,27,12]},index=['A','O','B','AB'])

# 카이제곱 적합도 검정 수행
chisq, p_value = stats.chisquare(df2['Observed'], df2['Expected'])

# 통계량과 p_value 출력
print("Chi-square test statistic:", chisq)
print("p-value:", p_value)

Output: p-value > 0.05로 귀무가설을 유지하므로 주어진 집단의 혈액형 비율은 알려진 비율과 동일하다고 볼 수 있습니다.

Chi-square test statistic: 3.6187363834422657
p-value: 0.305685769035246


2. 카이제곱 독립성 검정 (이원 카이제곱검정)

독립성 검정은 모집단의 두 범주형 변수 사이에 관계가 있는지 확인합니다. 변수 간의 독립성을 가정하여 분할표의 관측 빈도가 예상 빈도와 유의하게 다른지 여부를 평가합니다.

영어 성적과 수학 성적 간의 관계를 분석한다고 가정합니다. 아래는 200명의 학생의 영어, 수학 성적 데이터를 만드는 코드입니다.

import pandas as pd
import random

# Define the grade categories
english_grades = ['A', 'B', 'C']
math_grades = ['A', 'B', 'C']

# Create an empty DataFrame
df = pd.DataFrame(columns=["English Grade", "Math Grade"])

# Generate random grades for 200 students
for i in range(200):    
    english_grade = random.choice(english_grades)
    math_grade = random.choice(math_grades)        
    # Append the grades to the DataFrame
    df = pd.concat([df,pd.DataFrame({"English Grade": english_grade, "Math Grade": math_grade},index=[0])], ignore_index=True)

# # Print the DataFrame
print(df.head(3))

Output:

  English Grade Math Grade
0             A          B
1             A          B
2             C          C

Python에서 독립성 검정을 하기 위해서는 chi2_contingency 함수를 사용합니다. 그리고 분할표를 함수에 대해 입력합니다.

우선 분할표를 만듭니다. 분할표는 비교하려는 두 개 칼럼의 각 범주의 건수를 나타냅니다.

# Create a contingency table
contingency_table = pd.crosstab(df['English Grade'],df['Math Grade'])

# Print the contingency table
print(contingency_table)

Output:

Math Grade      A   B   C
English Grade            
A              23  27  22
B              25  18  16
C              19  27  23

이제 독립성 검정을 해봅니다.

from scipy.stats import chi2_contingency
# Perform the chi-squared test of independence
chi2_stat, p_val, dof, expected = chi2_contingency(contingency_table)

# Print the results
print("\nChi-square statistic:", chi2_stat)
print("P-value:", p_val)
print("Degrees of freedom:", dof)
print("Expected frequencies:")
print(expected)

Output:

Chi-square statistic: 3.3010464302469344
P-value: 0.5087664772958223
Degrees of freedom: 4
Expected frequencies:
[[24.12  25.92  21.96 ]
 [19.765 21.24  17.995]
 [23.115 24.84  21.045]]

 

유의 수준 > 0.05로 귀무가설이 유지되어 영어와 수학 등급은 독립입니다.

(변수의 독립이 기본적인 가정이므로 귀무가설이며, 독립적이지 않은 것이 대립가설이 됩니다.)

 

여기서 자유도는 (3-1) * (3-1) 이므로 4입니다. 자유도로 검산 결과 맞는 것을 확인했습니다.

 

3. 피셔의 정확검정

카이제곱 검정은 기대빈도의 크기가 5 이상이어야 합니다. 5보다 작으면 사례 수를 증가시키거나, 피셔의 정확검정을 사용해야 합니다. 

아래는 성별과 참석여부가 관련이 있는지 확인하는 예제입니다.

import scipy.stats as stats

# Create a contingency table
contingency_table=pd.DataFrame([[3, 5],[8, 4]], columns=['남자','여자'], index=['참석','불참'])

# Perform Fisher's exact test
statistic, p_value = stats.fisher_exact(contingency_table)

# Print the results
print("statistic:", statistic)
print("p-value:", p_value)

Output: p-value > 0.05 로서 귀무가설을 유지하여 성별과 참석여부 변수는 독립이라고 볼 수 있습니다.

Odds Ratio: 0.3
p-value: 0.36184805906168127

피셔의 정확검정은 scipy.stats.fisher_exact는 2X2의 contingency table만 입력이 가능합니다.

이론적으로 불가능한 것은 아니지만, python에서 제공되지 않고 있습니다. (R은 가능)

 

※ 위 내용은 "빅데이터 분석기사 실기 준비를 위한 캐글 놀이터"  및 "데이터마님 scipy tutorial"을 따라가며 공부한 내용입니다.

https://www.kaggle.com/datasets/agileteam/bigdatacertificationkr

 

Big Data Certification KR

빅데이터 분석기사 실기 (Python, R tutorial code)

www.kaggle.com

 

https://www.datamanim.com/dataset/97_scipy/scipy.html#t-one-sample

728x90

댓글