87일차 시작.... (ANOVA)

조동현·2022년 11월 9일
0

[교육] Python Analysis

목록 보기
12/15
post-thumbnail

📊 ANOVA (분산 분석)


📌 ANOVA란?

  • 분산 분석
    - ANOVA는 평균을 사용하지 않고 분산을 사용하여 차이 검정을 수행한다.
    - 3개 이상의 집단 간의 차이 분석을 할 때 사용하는 검정 방법


  • f-value
    - 집단 내 분산으로 집단 간 분산을 나눈 값
    - f-value = (집단 간 분산) / (집단 내 분산)

- A : 집단 내 분산은 크고, 집단 간 분산은 작다. 즉, f-value 값이 작아진다.
↪ [ f-value 작음 == p-value 큼 == 대립가설 기각 ]

- B : 집단 내 분산은 작고, 집단 간 분산은 크다. 즉, f-value 값이 커진다.
↪ [ f-value 큼 == p-value 작음 == 대립가설 채택 ]


  • f-value 특징
    - 집단 간의 분산 차이가 많이 날수록 좋음 == 최대한 독립된 집단들이 존재해야 함









📊 ANOVA 사후검정


📌 ANOVA 사후검정

  • 사후 검정
    - 각 집단 간의 평균 차이를 검정하는 것


  • 수행 이유
    - ANOVA 검정만 수행하면 전체 집단에 대한 평균차이 여부는 알려주나, 각 집단 간의 평균차이는 알려주지 않으므로 필수적으로 수행한다.
    - ANOVA 검정 : 전체 집단의 평균 차이 여부
    - 사후 검정 : 각 집단 간의 평균 차이 여부


  • 사용 검정 메소드
    - pairwise_tukeyhsd()
    - endog 속성 : 종속변수를 지정
    - groups 속성 : 독립변수를 지정


  • 사후검정 결과 시각화
    Tukey결과객체.plot_simultaneous()
    - xlabel : 'mean' 으로 지정
    - ylabel : 'group' 으로 지정









📊 실습1) 일원 ANOVA 검정 수행


📌 편의점 3개 지역 매출액에 대한 평균차이 검정 수행

  • 1. 가설 수립
    - 귀무가설 : 강남구에 있는 GS 편의점 알바생의 급여에 대한 평균은 차이가 없다.
    - 대립가설 : 강남구에 있는 GS 편의점 알바생의 급여에 대한 평균은 차이가 있다.

  • 2. 라이브러리 Import
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import urllib.request as request
import scipy.stats as stats
from statsmodels.formula.api import ols                     # ANOVA 검정 수행을 위한 선형회귀 모델
from statsmodels.stats.anova import anova_lm                # ANOVA 검정 모듈
from statsmodels.stats.multicomp import pairwise_tukeyhsd   # 사후 검정을 위한 모듈

  • 3. 데이터 준비
url = "https://raw.githubusercontent.com/pykwon/python/master/testdata_utf8/group3.txt"
data = pd.read_csv(url, header=None)
print(data.head())
#      0  1
# 0  243  1
# 1  251  1
# 2  275  1

  • 4. 데이터 결측치 확인
print(data.info())              # 결측치 없음
#  #   Column  Non-Null Count  Dtype
# ---  ------  --------------  -----
#  0   0       22 non-null     int64
#  1   1       22 non-null     int64

  • 5. 데이터 이상치 확인
print(data.describe())          # 0 칼럼에 이상치 1개 발견
#                 0          1
# count   22.000000  22.000000
# mean   283.227273   1.863636
# std     51.284391   0.774317
# min    206.000000   1.000000
# 25%    249.500000   1.000000
# 50%    274.000000   2.000000
# 75%    305.500000   2.000000
# max    392.000000   3.000000
# plt.boxplot(data)
# plt.show()
data = data[data[0] <= 390.0]
print(data.shape)
# (21, 2)    -> 1개의 이상치 제거

  • 6. 하나의 독립변수를 세 개의 집단으로 분리
df1 = data[data[1] == 1][0]
df2 = data[data[1] == 2][0]
df3 = data[data[1] == 3][0]

  • 7. 각 집단의 평균 확인
print(f'집단1의 평균 {df1.mean()}')
print(f'집단2의 평균 {df2.mean()}')
print(f'집단3의 평균 {df3.mean()}')
# 집단1의 평균 305.85714285714283
# 집단2의 평균 256.44444444444446
# 집단3의 평균 278.0

  • 8. 정규성 확인
# 만족:anova_lm, 불만족:kruskal-wallis
print(stats.shapiro(df1).pvalue)
print(stats.shapiro(df2).pvalue)
print(stats.shapiro(df3).pvalue)
# 0.3995428681373596
# 0.6561065912246704
# 0.832481324672699
# 정규성 분석 : 세가지 집단 모두 0.05(유의수준)보다 크므로 정규성 만족

  • 9. 등분산성 확인
# 만족:anova_lm, 불만족:welchi_anova
print(len(df1), '\t', len(df2), '\t', len(df3))
# 7      9      5    -> 비모수 검정
print(stats.bartlett(df1, df2, df3).pvalue)
# 0.5058687511020414
# 등분산성 분석 : 세 집단의 등분산성은 유의수준보다 높은 값을 갖으므로 등분산성 만족

  • 10. 데이터 산포도 시각화
plt.boxplot([df1, df2, df3], showmeans=True)
plt.show()

  • 11-1. 일원 분산 분석 : ANOVA 검정 전개 - anova_lm 검정
# 정규성, 등분산성 만족
data.columns = ['종속', '독립']
reg = ols('종속 ~ C(독립)', data=data).fit()        # 범주형 독립변수는 C() 로 묶어서 사용한다.
anova = anova_lm(reg, type=1)
print(anova)
#             df        sum_sq      mean_sq        F    PR(>F)
# C(독립)      2.0   9613.873016  4806.936508  2.60436  0.101529
# Residual  18.0  33223.079365  1845.726631      NaN       NaN
# 분산 분석표 결과 분석
# 0.10(p-value) > 0.05(유의수준)
# 대립가설의 p-value가 유의수준보다 크므로 유의미한 결과를 도출할 수 없다고 판단
# -> 대립가설 기각
# -> 귀무가설 채택
# -> 세 집단의 매출액 차이가 없다.

  • 11-2. 일원 분산 분석 : ANOVA 검정 전개 - f_oneway 검정
# 정규성, 등분산성 만족
f_sta, pvalue = stats.f_oneway(df1, df2, df3)
print('f통계량 : ', f_sta)
print('p-value : ', pvalue)
# f통계량 :  2.604359944846144
# p-value :  0.10152941015355345
# 결과 분석
# 0.10(p-value) > 0.05(유의수준)
# 대립가설의 p-value가 유의수준보다 크므로 유의미한 결과를 도출할 수 없다고 판단
# -> 대립가설 기각
# -> 귀무가설 채택
# -> 세 집단의 매출액 차이가 없다.

  • 12. 각 집단의 평균 차이 검정 : 사후검정 전개
tukey = pairwise_tukeyhsd(endog=data['종속'], groups=data['독립'])
print(tukey)
#  Multiple Comparison of Means - Tukey HSD, FWER=0.05 
# =====================================================
# group1 group2 meandiff p-adj   lower    upper  reject
# -----------------------------------------------------
#      1      2 -49.4127 0.0843 -104.669  5.8436  False
#      1      3 -27.8571 0.5219 -92.0592 36.3449  False
#      2      3  21.5556 0.6475  -39.602 82.7131  False
# -----------------------------------------------------
# 사후 검정 결과 분석
# 각 집단 간의 meandiff(평균차이)가 존재하지만 결과적으로 reject(평균차이여부)에서 큰 차이는 없다고 판단함

  • 13. 사후검정 결과 시각화
tukey.plot_simultaneous(xlabel='mean', ylabel='group')
plt.show()









📊 이원 ANOVA 검정


📌 이원 분산분석 - ANOVA 검정

  • 이원 분산분석이란?
    - 두 개 이상의 독립변수를 분산분석에 사용하는 것을 의미한다.
    - 많이 사용하지는 않는다.

  • 일원 분산분석과 차이점
    - 이원 분산분석 : 독립변수 간의 상호작용을 이용한 ANOVA 검정 수행
    ↪ [ ols('종속변수 ~ C(독립1) + C(독립2) + C(독립1):C(독립2)', data=데이터프레임) ]

📌

  • 1. 가설 수립
    - 귀무가설 :
    - 대립가설 :

  • 2. 라이브러리 Import
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import urllib.request as request
import scipy.stats as stats
from statsmodels.formula.api import ols                     # ANOVA 검정 수행을 위한 선형회귀 모델
from statsmodels.stats.anova import anova_lm                # ANOVA 검정 모듈
from statsmodels.stats.multicomp import pairwise_tukeyhsd   # 사후 검정을 위한 모듈

  • 3. 데이터 준비
url = "https://raw.githubusercontent.com/pykwon/python/master/testdata_utf8/group3.txt"
data = pd.read_csv(url, header=None)
print(data.head())
#      0  1
# 0  243  1
# 1  251  1
# 2  275  1

  • 4. 데이터 결측치 확인
print(data.info())              # 결측치 없음
#  #   Column  Non-Null Count  Dtype
# ---  ------  --------------  -----
#  0   0       22 non-null     int64
#  1   1       22 non-null     int64

  • 5. 데이터 이상치 확인
print(data.describe())          # 0 칼럼에 이상치 1개 발견
#                 0          1
# count   22.000000  22.000000
# mean   283.227273   1.863636
# std     51.284391   0.774317
# min    206.000000   1.000000
# 25%    249.500000   1.000000
# 50%    274.000000   2.000000
# 75%    305.500000   2.000000
# max    392.000000   3.000000
# plt.boxplot(data)
# plt.show()
data = data[data[0] <= 390.0]
print(data.shape)
# (21, 2)    -> 1개의 이상치 제거

  • 6. 하나의 독립변수를 세 개의 집단으로 분리
df1 = data[data[1] == 1][0]
df2 = data[data[1] == 2][0]
df3 = data[data[1] == 3][0]

  • 7. 각 집단의 평균 확인
print(f'집단1의 평균 {df1.mean()}')
print(f'집단2의 평균 {df2.mean()}')
print(f'집단3의 평균 {df3.mean()}')
# 집단1의 평균 305.85714285714283
# 집단2의 평균 256.44444444444446
# 집단3의 평균 278.0

  • 8. 정규성 확인
# 만족:anova_lm, 불만족:kruskal-wallis
print(stats.shapiro(df1).pvalue)
print(stats.shapiro(df2).pvalue)
print(stats.shapiro(df3).pvalue)
# 0.3995428681373596
# 0.6561065912246704
# 0.832481324672699
# 정규성 분석 : 세가지 집단 모두 0.05(유의수준)보다 크므로 정규성 만족

  • 9. 등분산성 확인
# 만족:anova_lm, 불만족:welchi_anova
print(len(df1), '\t', len(df2), '\t', len(df3))
# 7      9      5    -> 비모수 검정
print(stats.bartlett(df1, df2, df3).pvalue)
# 0.5058687511020414
# 등분산성 분석 : 세 집단의 등분산성은 유의수준보다 높은 값을 갖으므로 등분산성 만족

  • 10. 데이터 산포도 시각화
plt.boxplot([df1, df2, df3], showmeans=True)
plt.show()

  • 11-1. 일원 분산 분석 : ANOVA 검정 전개 - anova_lm 검정
# 정규성, 등분산성 만족
data.columns = ['종속', '독립']
reg = ols('종속 ~ C(독립)', data=data).fit()        # 범주형 독립변수는 C() 로 묶어서 사용한다.
anova = anova_lm(reg, type=1)
print(anova)
#             df        sum_sq      mean_sq        F    PR(>F)
# C(독립)      2.0   9613.873016  4806.936508  2.60436  0.101529
# Residual  18.0  33223.079365  1845.726631      NaN       NaN
# 분산 분석표 결과 분석
# 0.10(p-value) > 0.05(유의수준)
# 대립가설의 p-value가 유의수준보다 크므로 유의미한 결과를 도출할 수 없다고 판단
# -> 대립가설 기각
# -> 귀무가설 채택
# -> 세 집단의 매출액 차이가 없다.

  • 11-2. 일원 분산 분석 : ANOVA 검정 전개 - f_oneway 검정
# 정규성, 등분산성 만족
f_sta, pvalue = stats.f_oneway(df1, df2, df3)
print('f통계량 : ', f_sta)
print('p-value : ', pvalue)
# f통계량 :  2.604359944846144
# p-value :  0.10152941015355345
# 결과 분석
# 0.10(p-value) > 0.05(유의수준)
# 대립가설의 p-value가 유의수준보다 크므로 유의미한 결과를 도출할 수 없다고 판단
# -> 대립가설 기각
# -> 귀무가설 채택
# -> 세 집단의 매출액 차이가 없다.

  • 12. 각 집단의 평균 차이 검정 : 사후검정 전개
tukey = pairwise_tukeyhsd(endog=data['종속'], groups=data['독립'])
print(tukey)
#  Multiple Comparison of Means - Tukey HSD, FWER=0.05 
# =====================================================
# group1 group2 meandiff p-adj   lower    upper  reject
# -----------------------------------------------------
#      1      2 -49.4127 0.0843 -104.669  5.8436  False
#      1      3 -27.8571 0.5219 -92.0592 36.3449  False
#      2      3  21.5556 0.6475  -39.602 82.7131  False
# -----------------------------------------------------
# 사후 검정 결과 분석
# 각 집단 간의 meandiff(평균차이)가 존재하지만 결과적으로 reject(평균차이여부)에서 큰 차이는 없다고 판단함

  • 13. 사후검정 결과 시각화
tukey.plot_simultaneous(xlabel='mean', ylabel='group')
plt.show()









profile
데이터 사이언티스트를 목표로 하는 개발자

0개의 댓글