- 분산 분석
- ANOVA는 평균을 사용하지 않고 분산을 사용하여 차이 검정을 수행한다.
- 3개 이상의 집단 간의 차이 분석을 할 때 사용하는 검정 방법
- f-value
- 집단 내 분산으로 집단 간 분산을 나눈 값
- f-value = (집단 간 분산) / (집단 내 분산)
- A : 집단 내 분산은 크고, 집단 간 분산은 작다. 즉, f-value 값이 작아진다.
↪ [ f-value 작음 == p-value 큼 == 대립가설 기각 ]- B : 집단 내 분산은 작고, 집단 간 분산은 크다. 즉, f-value 값이 커진다.
↪ [ f-value 큼 == p-value 작음 == 대립가설 채택 ]
- f-value 특징
- 집단 간의 분산 차이가 많이 날수록 좋음 == 최대한 독립된 집단들이 존재해야 함
- 사후 검정
- 각 집단 간의 평균 차이를 검정하는 것
- 수행 이유
- ANOVA 검정만 수행하면 전체 집단에 대한 평균차이 여부는 알려주나, 각 집단 간의 평균차이는 알려주지 않으므로 필수적으로 수행한다.
- ANOVA 검정 : 전체 집단의 평균 차이 여부
- 사후 검정 : 각 집단 간의 평균 차이 여부
- 사용 검정 메소드
- pairwise_tukeyhsd()
- endog 속성 : 종속변수를 지정
- groups 속성 : 독립변수를 지정
- 사후검정 결과 시각화
Tukey결과객체.plot_simultaneous()
- xlabel : 'mean' 으로 지정
- ylabel : 'group' 으로 지정
- 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 검정 수행
↪ [ 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()