본문 바로가기
Data Analysis/Scipy

2. [Python] ANOVA

by 베짱이28호 2022. 9. 25.

2. [Python] ANOVA

분산분석(ANOVA) 이해하는 가장 좋은 방법(1)

분산분석(ANOVA) 이해하는 가장 좋은 방법(2)

참고 자료.


1. ANOVA

  • 세 개 이상의 집단의 평균을 비교할 때 사용되는 분석
  • 평균 대신 분산을 사용하여 검정하는 이유
    • t 검정의 한계 : 3개 이상의 집단에서 각각 평균을 비교하는 경우, 신뢰구간이 변화하여 오류를 범하기 쉬워진다.
  • F통계량을 사용하여 검정한다.
    • F 통계량 : 집단 간 분산 / 집단 내 분산
    • 집단 간 분산 : (집단1의 크기)*(집단1의 평균-전체평균)^2 + ...
    • 집단 내 분산 : (집단1의 표본-집단1의 표본평균)^2 + ... 
    • 이 F 통계량이 클수록 집단 간 평균 차이가 유의미하다고 주장할 수 있다.
    • 집단에서 데이터는 집단의 평균에 잘 밀집되어있고, 집단 간 평균은 차이난다는 의미.
import numpy as np
from scipy.stats import f_oneway

np.random.seed(42)
group1 = np.random.normal(loc=75, scale=5, size=25)  # 평균 70
group2 = np.random.normal(loc=73, scale=5, size=35)  # 평균 75
group3 = np.random.normal(loc=71, scale=5, size=30)  # 평균 80

# ANOVA 분석 수행
f_stat, p_val = f_oneway(group1, group2, group3)

print(f"F 통계량: {f_stat:.4f}")
print(f"p-값: {p_val:.4f}")

F 통계량: 3.0109
p-값: 0.0544
  • 전체 평균의 가중치가 73쪽에 가까운데, group 2의 sample 수를 늘리면 집단 간 분산이 커져서 p값이 작아진다.
  • 현재 결과는 p가 0.05보다 크기 때문에 집단 간 차이가 유의미하게 난다고 주장할 수 없다.

 

2. 일원배치 분산분석

from scipy import stats
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd

plt.style.use('seaborn-v0_8')
plt.rc('font', family='Malgun Gothic')
plt.rcParams['axes.unicode_minus'] = False

np.random.seed(42)
data = {
    'score': np.concatenate([
        np.random.normal(70, 5, 30),  # A반 10대
        np.random.normal(68, 5, 30),  # A반 20대
        np.random.normal(67, 5, 30),  # A반 30대
        np.random.normal(72, 5, 30),  # B반 10대
        np.random.normal(70, 5, 30),  # B반 20대
        np.random.normal(69, 5, 30),  # B반 30대
        np.random.normal(74, 5, 30),  # C반 10대
        np.random.normal(72, 5, 30),  # C반 20대
        np.random.normal(70, 5, 30)   # C반 30대
    ]),
    'group': ['A']*90 + ['B']*90 + ['C']*90,
    'age_group': ['10s']*30 + ['20s']*30 + ['30s']*30 + 
                 ['10s']*30 + ['20s']*30 + ['30s']*30 + 
                 ['10s']*30 + ['20s']*30 + ['30s']*30
}
df = pd.DataFrame(data)
  • 점수, 그룹, 나이대로 이루어진 데이터가 있다.

1. Scipy 코드

# 그룹별 데이터 분리
grouped_data = [df[df['group'] == g]['score'] for g in df['group'].unique()]

# 일원배치 분산분석 수행
f_stat, p_value = stats.f_oneway(*grouped_data)

# 결과 출력
print(f"F-통계량: {f_stat:.3f}")
print(f"p-값: {p_value:.3f}")

F-통계량: 15.004
p-값: 0.000
  • f_oneway을 사용하여 반/나이에 따른 차이를 확인할 수 있다.
  • p value가 0.00로 대립가설을 채택한다.

 

3. 이원배치 분산분석

1. Scipy 코드

import statsmodels.api as sm
from statsmodels.formula.api import ols

# 이원배치 분산분석 모델 설정
model = ols('score ~ C(group) + C(age_group) + C(group):C(age_group)', data=df).fit()

# 분산분석표 생성
anova_table = sm.stats.anova_lm(model, typ=2)

# 결과 출력
print(anova_table)

                            sum_sq     df          F        PR(>F)
C(group)                790.871732    2.0  15.887253  3.083160e-07
C(age_group)            387.981159    2.0   7.793874  5.156887e-04
C(group):C(age_group)   152.732287    4.0   1.534065  1.926442e-01
Residual               6496.325008  261.0        NaN           NaN
  • 그룹, 연령대는 p value가 0.00으로 대립가설을 채택할 수 있다.
  • (그룹, 연령대)의 경우 0.19로 대립가설을 채택할 수 없다.

'Data Analysis > Scipy' 카테고리의 다른 글

4. [Python] Chi-Square test  (0) 2022.10.08
3. [Python] Time Series Decomposition  (0) 2022.10.02
1. [Python] T-test  (0) 2022.08.29

댓글