2. [Python] ANOVA
참고 자료.
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 |
댓글