본문 바로가기
공부/통계학

일원분산분석 (One-way ANOVA) python

by signature95 2022. 2. 15.
728x90
반응형

분산 분석은 연속형 반응 변수와 범주형 설명 변수를 갖는 데이터를 분석하는 방법 중 하나입니다.

 

의사결정 흐름도는 다음과 같습니다.

따라서 일원 분산 분석은 연속형 target이 1개고 범주형 feature 1개를 갖는 데이터에서 그룹이 3개 이상인 경우 사용합니다.

동일한 조건에서 그룹이 2개인 경우에는 t-test를 사용합니다.

 

t-test에 대한 포스트는 여기를 참고하시면 됩니다.

2021.11.17 - [공부/통계학] - T-test (T 검정)

 

T-test (T 검정)

t 검정의 적용은 언제 하는 것일까? https://ko.wikipedia.org/wiki/T-테스트 t-테스트 - 위키백과, 우리 모두의 백과사전 t-테스트(t-test) 또는 t-검정 또는 스튜던트 t-테스트(Student's t-test)는 검정통계량..

signature95.tistory.com

 

일원분산분석을 시행하는 경우, feature로 설명되지 않는 target 변수에 대한 정보로 error (오차)에 대한 가정이 존재합니다.

 

오차에 대한 가정 error ~ N(0,σ^2) (각 링크에 검정 방식을 소개합니다)

 

또한, 각 그룹의 모평균이 동일하다는 귀무가설을 기각하는 경우, 다중비교 (사후 검정)의 절차가 필요합니다.

 

분산 분석은 target의 변동(TSS : Total Sum of Squares)각 그룹 간 차이에 대한 target 변동(SST : Sum of Squares for Treatment) + 그룹 간 차이 외적인 변동(SSE : Sum of Squares for Error)으로 분해한 후, SST가 SSE보다 크면 클수록 그룹의 평균 차이가 통계적으로 유의하다고 할 수 있습니다.

 

One-way ANOVA 분산 분석표

요인
(factor)
자유도
(degree of freedom)
제곱합
(sum of square)
평균제곱합
(Mean Square)
F 값
Treatment k-1 SST MST = SST/(k-1) F = MST/MSE
Error n-k SSE MSE = SSE/(n-k)  
Total n-1 TSS    

위의 식에서 k는 그룹의 개수를 의미하고 n은 전체 데이터 개수를 의미합니다.

먼저 Between Variance로 표현되는 MST는 전체평균 - 그룹평균의 제곱합을 자유도로 나눈 값입니다.

Within Variance로 표현되는 MSE는 그룹평균 - 샘플데이터의 제곱합을 자유도로 나눈 값입니다.

 

검정통계량은 F 값을 이용하는데, MST가 MSE보다 클수록, 그룹별 target 변수의 평균 차이가 유의하기 때문에 F 값이 커지게 되는 구조입니다. F 값이 커지게 된다면, 귀무가설을 기각할 정도의 p값이 나오게 될 것입니다. 따라서 유의 수준 (일반적으로 5%)에 대해 귀무가설을 기각할 수 있다는 결과를 가져올 수 있게 됩니다.

 

그렇다면 바로 코드를 시행해보도록 하겠습니다.

먼저 데이터는 iris 데이터입니다.

 

https://www.kaggle.com/uciml/iris

 

Iris Species

Classify iris plants into three species in this classic dataset

www.kaggle.com

 

csv 다운로드

iris.csv
0.00MB

 

import pandas as pd

# csv파일이 있는 경로입니다.
path = '../dataset/'

data = pd.read_csv(path+'iris.csv', names=['sepal_length', 'sepal_width', 'petal_length', 'petal_width','target'])
data

>>>

     sepal_length  sepal_width  petal_length  petal_width          target
0             5.1          3.5           1.4          0.2     Iris-setosa
1             4.9          3.0           1.4          0.2     Iris-setosa
2             4.7          3.2           1.3          0.2     Iris-setosa
3             4.6          3.1           1.5          0.2     Iris-setosa
4             5.0          3.6           1.4          0.2     Iris-setosa
..            ...          ...           ...          ...             ...
145           6.7          3.0           5.2          2.3  Iris-virginica
146           6.3          2.5           5.0          1.9  Iris-virginica
147           6.5          3.0           5.2          2.0  Iris-virginica
148           6.2          3.4           5.4          2.3  Iris-virginica
149           5.9          3.0           5.1          1.8  Iris-virginica

[150 rows x 5 columns]

 

그다음은 데이터의 정보와 기초통계입니다.

data.info()

data.describe()

>>>

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 150 entries, 0 to 149
Data columns (total 5 columns):
 #   Column        Non-Null Count  Dtype  
---  ------        --------------  -----  
 0   sepal_length  150 non-null    float64
 1   sepal_width   150 non-null    float64
 2   petal_length  150 non-null    float64
 3   petal_width   150 non-null    float64
 4   target        150 non-null    object 
dtypes: float64(4), object(1)
memory usage: 6.0+ KB


       sepal_length  sepal_width  petal_length  petal_width
count    150.000000   150.000000    150.000000   150.000000
mean       5.843333     3.054000      3.758667     1.198667
std        0.828066     0.433594      1.764420     0.763161
min        4.300000     2.000000      1.000000     0.100000
25%        5.100000     2.800000      1.600000     0.300000
50%        5.800000     3.000000      4.350000     1.300000
75%        6.400000     3.300000      5.100000     1.800000
max        7.900000     4.400000      6.900000     2.500000

 

일원분산분석을 적용하는 데이터는 꽃받침의 폭으로 각 그룹별로 꽃받침의 폭 평균이 유의한 차이를 보이는지 검정해보고자 합니다.

먼저 target 데이터에 대해 ANOVA 분산분석을 시행하기 앞서 ordinal encoding을 적용합니다.

(물론 굳이 할 필요는 없지만, 분석의 편의를 위해 시행함)

 

# target 변수에 대해 0,1,2로 라벨링 과정을 시행
from sklearn.preprocessing import OrdinalEncoder

encoder = OrdinalEncoder()
data = pd.DataFrame(encoder.fit_transform(data))
data.columns = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width','target']

 

이번엔 시각화를 통해 먼저 데이터를 확인해봅니다.

# 시각화 시행

sns.barplot(x= data['target'], y=data['sepal_width'])
plt.title('꽃 종류별 꽃 받침의 폭')
plt.show()

 

시각적으로도 평균이 다르다는 것을 알 수 있는데요, 통계적으로도 유의하게 다른지 검정해보겠습니다.

 

먼저 정규성검정을 합니다. (유의수준 5%로 설정한 shapiro 검정)

 

# 정규성 검정
# 귀무가설 : 정규분포를 따른다.
from  scipy.stats import shapiro

for i in range(3):
    p_value = shapiro(data.sepal_width[data.target==i])[1]
    if p_value < 0.05:
        print('정규분포를 따른다는 귀무가설을 유의수준 5%에서 기각할 수 있습니다. 따라서 정규성을 충족하지 못합니다.')
    else:
        print('정규분포를 따른다는 귀무가설을 유의수준 5%에서 기각할 수 없습니다. 따라서 정규성을 충족합니다.')

>>>

정규분포를 따른다는 귀무가설을 유의수준 5%에서 기각할 수 없습니다. 따라서 정규성을 충족합니다.
정규분포를 따른다는 귀무가설을 유의수준 5%에서 기각할 수 없습니다. 따라서 정규성을 충족합니다.
정규분포를 따른다는 귀무가설을 유의수준 5%에서 기각할 수 없습니다. 따라서 정규성을 충족합니다.

등분산성 검정

#등분산성 확인 - 레빈 검증 (귀무가설 : 등분산의 특징이 있다.)
from scipy.stats import levene
print(levene(data.sepal_width[data.target==0],
             data.sepal_width[data.target==1],
             data.sepal_width[data.target==2]))

#등분산성 확인 - 바틀렛 검증 (귀무가설 : 등분산의 특징이 있다.)
from scipy.stats import bartlett
print(bartlett(data.sepal_width[data.target==0],
               data.sepal_width[data.target==1],
               data.sepal_width[data.target==2]))
               
>>>

LeveneResult(statistic=0.6280767321673624, pvalue=0.5350428817228079)
BartlettResult(statistic=2.1232079705400917, pvalue=0.3459005457507166)

 

이제 등분산성과 정규성을 충족하였기 때문에 일원분산분석을 시행할 수 있습니다.

 

이를 시행하기 위해서는 statsmodel의 anova 매서드와 ols 매서드를 호출해줍니다.

from statsmodels.formula.api import ols
from statsmodels.stats.anova import anova_lm, anova_single

model = ols('sepal_width ~ C(target)', data).fit()

anova_table = anova_lm(model)

if anova_table['PR(>F)'][0] < 0.05:
    print(f'ANOVA 분석 결과, 5%의 유의수준으로 모든 수준에서 모평균이 동일하다는 귀무가설을 기각할 수 있습니다. 따라서 위 집단의 모평균이 다르다고 말할 수 있습니다.')
else:
    print(f'ANOVA 분석 결과, 5%의 유의수준으로 모든 수준에서 모평균이 동일하다는 귀무가설을 기각할 수 없습니다.')
    
print(anova_table)


>>>

ANOVA 분석 결과, 5%의 유의수준으로 모든 수준에서 모평균이 동일하다는 귀무가설을 기각할 수 있습니다. 따라서 위 집단의 모평균이 다르다고 말할 수 있습니다.
              df   sum_sq     mean_sq          F        PR(>F)
C(target)    2.0  1084.84  542.420000  47.733947  1.061054e-16
Residual   147.0  1670.42   11.363401        NaN           NaN

이번에는 OLS 회귀 요약을 보도록합니다.

model.summary()

>>>

                            OLS Regression Results                            
==============================================================================
Dep. Variable:            sepal_width   R-squared:                       0.394
Model:                            OLS   Adj. R-squared:                  0.385
Method:                 Least Squares   F-statistic:                     47.73
Date:                Wed, 16 Feb 2022   Prob (F-statistic):           1.06e-16
Time:                        16:37:13   Log-Likelihood:                -393.61
No. Observations:                 150   AIC:                             793.2
Df Residuals:                     147   BIC:                             802.2
Df Model:                           2                                         
Covariance Type:            nonrobust                                         
====================================================================================
                       coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------------
Intercept           13.1600      0.477     27.605      0.000      12.218      14.102
C(target)[T.1.0]    -6.4400      0.674     -9.552      0.000      -7.772      -5.108
C(target)[T.2.0]    -4.4200      0.674     -6.556      0.000      -5.752      -3.088
==============================================================================
Omnibus:                        1.311   Durbin-Watson:                   1.866
Prob(Omnibus):                  0.519   Jarque-Bera (JB):                0.916
Skew:                           0.043   Prob(JB):                        0.633
Kurtosis:                       3.373   Cond. No.                         3.73
==============================================================================

Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.

여기서 F값, prob를 보면 47.73, 1.06e-16인 것을 알 수 있습니다.

이 값이 바로 one-way anova로 도출한 F값과 p값 입니다.

 

 

결론입니다. 

 

각 꽃 종류별 꽃받침의 폭의 평균이 동일하다는 귀무가설을 기각할 수 있기에 각 집단의 평균이 통계적으로 유의하게 다르다는 것도 증명할 수 있습니다.

728x90

댓글