areum

[ML] One-way ANOVA(일원 분산 분석) 본문

Programming/Machine Learning

[ML] One-way ANOVA(일원 분산 분석)

armmy 2023. 3. 24. 16:22
728x90

일원 분산 분석 정의


ANOVA(분석분석)은 '세 집단 또는 그 이상의 집단 간의 평균 차이가 유의미한가'를 확인하기 위해 사용하는 분석 방법입니다. 

그중 일원 분산 분석은 하나의 다른 척도를 가지고 보는 것을 일원 분산 분석이라고 합니다.

파이썬에서 One-way ANOVA 분석은 scipy.stats이나 statsmodel 라이브러리를 이용해서 할 수 있습니다. (statsmodel라이브러리가 좀 더 많고 규격화된 정보를 제공합니다.)

iris데이터로 일원 분산 분석 해보기


1. 필요한 라이브러리 및 패키지 불러오기 & 데이터 불러오기 

import pandas as pd
from statsmodels.formula.api import ols
from statsmodels.stats.anova import anova_lm
import statsmodels.stats.multicomp as mc

df = pd.read_csv("sample_data/iris.csv")

iris.csv
0.00MB

2. 데이터 확인하기

위 데이터를 가지고 iris의 꽃 종류를 독립 변수로 Petalwidth를 종속 변수로 설정하여 진행할 예정입니다.

3. boxplot을 통해 Petalwidth의 분포 확인

df.boxplot(column=['SepalWidthCm'], by=['Species'])

위 boxplot을 통해 setosa, versicolor, virginica의 중앙값, 이상치 등을 알 수 있었습니다.

4. Statsmodel을 사용한 일원분산분석

df.columns = ['SepalLength','SepalWidth','PetalLength','PetalWidth','Species']
fit = ols(formula='SepalWidth ~ C(Species)', data=df).fit()
anova_lm(fit)

  - 위 분산분석 표 해석

  • SSR : 표본평균과 종속변수 값 중 독립변수에 의해 설명된 부분과의 차이를 제곱하여 합한 것
  • SSE : 잡차들이 자신의 표본평균으로부터 벗어난 편차의 제곱

5. 사후검정

사후검정을 하는 이유는 다음과 같습니다.

t-test로는 A,B집단을 비교하여 두 집단 간의 차이가 있는지 없는지를 알려줍니다. 하지만 집단이 많아진 분산 분석은 서로 유의한 차이가 존재하는지의 '여부'만을 알려줍니다. 즉 A, B, C집단일 경우 A and B , A and C, B and C 이 세가지 중 어떠한 집단 간의 차이가 있는지를 알 수 없습니다.

그렇기에 어떠한 집단과 어떠한 집단이 차이가 있다는 것인지 알기 위해 '사후 분석'이 필요합니다.

그러나! 의차가 발생하지 않아 A=B=C라면 굳이 사후분석을 할 이유가 없습니다.

comp = mc.MultiComparison(df['SepalLength'], df['Species'])
tukeyhsd = comp.tukeyhsd(alpha=0.05)
tukeyhsd.summary()

print(tukeyhsd)
fig = tukeyhsd.plot_simultaneous()

위 사후검정을 통해 setosa, versicolor, virginica은 평균이 유의미한 차이가 없다는 것을 알 수 있습니다.

6. 분포 확인해 보기

colour = ['red', 'green', 'blue']

df_new = df.drop_duplicates(subset = "Species")
df_new= sorted(df_new['Species'])
group=[]
match={}
for i in range(len(df_new)):
    group.append(str(df_new[i]))
    match[group[i]]=colour[i]
    
for group in match:
    subset = df[df['Species'] == group]
    sns.distplot(subset['PetalWidth'],
                 hist = True,
                 kde = True,
                 kde_kws = {'linewidth': 2},
                 color = match[group],
                 label = group)