분산분석 ANOVA
: 분산 분석(ANOVA;변량 분석)은 3개 이상 다수의 집단을 비교할 때 사용하는 가설검정 방법이다.F값
= 집단간분산(between variance)
/ 집단내분산(within variance)
기반의 F분포를 이용함F분포
: 서로 다른 두개 이상의 모집단의 분산이 같은지를 확인할 때 사용함.(A 그림)
- 그룹 사이의 차이가 없음(B 그림)
- 그룹 사이의 유의한 차이가 존재세 집단 이상의 평균비교에서는 독립인 두 집단의 평균 비교(Ttest)를 반복하여 실시할 경우에 제1종 오류가 증가하게 되어 문제가 발생한다.
이를 해결하기 위해 Fisher가 개발한 분산분석(ANOVA, AN alysis Of Variance)을 이용하게 된다.
[reference]
일원 분산분석 ( one - way ANOVA )
하나의 다른 척도를 가지고 보는 것을 일원 분산분석이라고 함.
이원 분산분석 ( two -way ANOVA )
두 가지 요인을 기준으로 집단 간의 차이를 조사하는 것.
다원 분산 분석 ( multi - way ANOVA )
세 가지 이상의 요인을 기준으로 집단 간의 차이를 조사하는 것
다변량 분산분석 ( multi - variate ANOVA )
독립변수 1개 이상에 대해 종속변수 2개 이상으로 조사하는 것
* 서로 독립인 세 집단의 평균 차이 검정
실습) 세 가지 교육방법을 적용하여 1개월 동안
교육받은 교육생 80명을 대상으로 실기시험을 실시. three_sample.csv'
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 no 80 non-null int64
1 method 80 non-null int64
2 survey 80 non-null int64
3 score 80 non-null int64
분석
from statsmodels.formula.api import ols
from statsmodels.stats.anova import anova_lm
시각화
from statsmodels.stats.multicomp import pairwise_tukeyhsd
가설
from statsmodels.formula.api import ols
:
statsmodels 라이브러리는 추정 및 검정, 회귀분석(시계열 분석) 등의 기능을 제공함
data = pd.read_csv("../testdata/three_sample.csv")
print(data.info())
#outlier 이상치가 존재하므로 제거함
data = data.query('score <= 100')
# 세가지 교육방법 별 데이터 분류
result = data[['method','score']]
m1 = result[result['method']==1]
m2 = result[result['method']==2]
m3 = result[result['method']==3]
score1 = m1['score']
score2 = m2['score']
score3 = m3['score']
만족 anova
불만족 welch-anova
print('등분산성 확인 : ',stats.levene(score1,score2,score3).pvalue)
# 등분산성 확인 : 0.1132
등분산성이 0.05보다 크므로 만족
welch-anova
메소드 사용만족 : anova
불만족 : Kruskal Wallis test / kolmogorov-Smirnov Test
#정규성 만족 확인 :
print('12정규성 확인 : ',stats.ks_2samp(score1,score2).pvalue)
print('13정규성 확인 : ',stats.ks_2samp(score1,score3).pvalue)
print('23정규성 확인 : ',stats.ks_2samp(score2,score3).pvalue) # 모두 0.05를 넘기므로 만족
분산분석 방법1
anova
메소드 사용 전 빈도표를 만들어 선형회귀 분석 모델을 생성해야함.C(method)
R 분석과 같은 결과를 추출해내기 위해 C 예약어로 감싼다.from statsmodels.formula.api import ols
from statsmodels.stats.anova import anova_lm
data2 = pd.crosstab(data['method'],data['survey'])
data2.index=['방법1','방법2','방법3']
data2.columns=['만족','불만족']
print(data2)
#선형회귀 분석 모델 생성.
import statsmodels.api as sm
reg = ols('score ~ C(method)',data).fit() #종속변수 ~ 독립변수
table = sm.stats.anova_lm(reg,type=1)
print(table)
= 결과 =
df sum_sq mean_sq F PR(>F)
method 1.0 27.980888 27.980888 0.122228 0.727597
Residual 76.0 17398.134497 228.922822 NaN NaN
# pvalue = 0.7275 > 0.05 이므로 귀무 채택.
# 세 가지 교육방법에 따른 시험점수는 차이가 없다.
또는
분산분석 방법2 f_oneway
f_statistic,pvalue = stats.f_oneway(score1,score2,score3)
print('f_statistic: {} ,pvalue = {}'.format(f_statistic,pvalue))
방법1 결과와 같음. : f_statistic: 0.06231 ,pvalue = 0.93963
3개의 자료를 얻었다면 바로 사용 가능함. 빈도표와 선형회귀 분석 모델을 작성하지 않아도 된다.
Post Hoc Test : Turkey , Dunnett, Sheffe ...
ANOVA 분석 결과가 통계적으로 유의하다는 결과를 얻었을 경우,
그것은 집단별로 차이가 있다는것까지는 도출가능하지만, 어떤 집단간에 차이가 있는지는 알려주지 않는다.
N개의의 집단 중 어떤집단들 간에 값이 차이가 있는지를 추가적으로 살펴보기 위해서 실시하는것이 사후 분석이다.
from statsmodels.stats.multicomp import pairwise_tukeyhsd
turkey_result = pairwise_tukeyhsd(endog=data.score,groups=data.method)
print(turkey_result)
Multiple Comparison of Means - Tukey HSD, FWER=0.05
=====================================
group1 group2 meandiff p-adj lower upper reject
----------------------------------------------------
1 2 0.9725 0.9702 -8.9458 10.8909 False
1 3 1.4904 0.9363 -8.8183 11.799 False
2 3 0.5179 0.9918 -9.6125 10.6483 False
----------------------------------------------------
reject가 False인것으로 보아 유의미한 차이가 아님.
이를 시각화 할 수도 있다.
turkey_result.plot_simultaneous(xlabel='mean',ylabel='group')
plt.show()
거의 모든 직선이 동일선상에 존재하기 때문에 reject가 False인 것을 시각적으로 확인했다.
다른 사후검정법은 이곳에서 확인하자
요약
데이터를 가공
stats.levene
: 등분산성 만족 확인.
anova
welch-anova
stats.ks_2samp
: 정규성 만족 확인. 모든 케이스를 비교한다.
anova
Kruskal Wallis test / kolmogorov-Smirnov Test
등분산성과 정규성 만족 여부에 따라 메소드를 사용한다.
단, 불만족일시 무조건 조건에 맞도록 하나의 메소드를 사용하여 결과를 도출하려 하지 말고, 만족/불만족 모두 분석하여 정리하는 것이 좋다.
ex) 등분산성 불만족, 정규성 만족시 일단 정설대로 분석을 하고 등분산성 만족시 분석을 첨언한다.
분산분석
pd.crosstab
: 빈도표를 작성하여 선형회귀 분석모델을 생성한다. 하단 코드
: 분석모델과 메소드를 사용하여 분산분석을 한다.import statsmodels.api as sm
reg = ols('score ~ C(method)',data).fit() #종속변수 ~ 독립변수
table = sm.stats.anova_lm(reg,type=1)
pairwise_tukeyhsd
df sum_sq mean_sq F PR(>F)
method 1.0 27.980888 27.980888 0.122228 0.727597
Residual 76.0 17398.134497 228.922822 NaN NaN
df
: 자유도sum_sq
: SSRResidual-sum_sq
: SSEmean_sq
: MSRResidual-mean_sq
: MSEMSR / MSE = F
: 이 F값에 의해 p-value를 얻게되는것.
SSE + SSR의 합
: Y의 총 변동(SST)은 직선으로 설명 불가능한 변동 SSE와 직선으로 설명 가능한 변동 SSR로 되어있다.reference : https://acdongpgm.tistory.com/70
Two-way Anova 이원배치 분산 분석 : 목적요인이 두개인 경우
태아수, 관측자 수 요인에 따른 집단이 태아의 머리둘레 평균값에 영향을 주는지 검증
! 교호작용, 상호작용(interaction) 효과
data = pd.read_csv("../testdata/group3_2.txt")
print(data.head(3))
print(set(data['태아수']),set(data['관측자수'])) #{1, 2, 3} {1, 2, 3, 4}
# data.boxplot(columns='머리둘레',by='태아수')
# plt.show()
# data.boxplot(columns='머리둘레',by='관측자수')
# plt.show()
# 교호작용, 상호작용(interaction) 효과 :
# 특정변인의 효과가 다른 변인의 수준에 따라 달라지는것
# ANOVA 분석시 상호작용을 뺀 경우
reg = ols("data['머리둘레']~C(data['태아수']) + C(data['관측자수'])",data=data).fit()
result = anova_lm(reg,type=2)
print(result)
# ANOVA 분석시 상호작용을 적용한 경우
reg = ols("머리둘레~C(태아수) + C(관측자수) + C(태아수):C(관측자수)",data=data).fit()
result = anova_lm(reg,type=2)
print(result)
# df sum_sq mean_sq F PR(>F)
# C(태아수) 2.0 324.008889 162.004444 2113.101449 1.051039e-27
# C(관측자수) 3.0 1.198611 0.399537 5.211353 6.497055e-03
# C(태아수):C(관측자수) 6.0 0.562222 0.093704 1.222222 3.295509e-01
# Residual 24.0 1.840000 0.076667 NaN NaN