ADP 실기 12장 Statisitc test
본 게시물은 다양한 통계적 검정 방법에 대해 소개한다.
1. T-검정
1.1 Concept
특정 집단의 평균 값을 추정하거나 차이를 검정할 때 사용
- 검정 통계량이 귀무가설 하에서 t-distribution을 따름
- 종속변수는 연속형 변수(평균값)
- 독립변수는 범주형 변수
- t-통계량: 분산을 사용하여 차이를 통계적으로 표현한 것
1.2 t-통계량
- 표본이 1개일 때
- 표본이 2개일 때
2. 일표본 T-검정
2.1 Concept
단일 모집단에서 관심이 있는 연속형 변수의 평균값을 특정 기준값과 비교
- 모집단의 구성요소들이 정규분포를 이뤄야함
- 종속변수는 연속형
- 검증하고자 하는 기준값이 있어야 함
2.2 Hypothesis
- 귀무가설: 모평균의 값은 x이다.
- 대립가설: 모평균의 값은 x가 아니다.
2.2 Implementation
😗 cat의 몸무게가 2.6kg인지 아닌지 검정
import pandas as pd
cats=pd.read_csv("https://raw.githubusercontent.com/ADPclass/ADP_book_ver01/main/data/cats.csv")
cats
cats.info()
RangeIndex: 144 entries, 0 to 143
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Sex 144 non-null object
1 Bwt 144 non-null float64
2 Hwt 144 non-null float64
dtypes: float64(2), object(1)
- Bwt는 몸무게
import scipy.stats as stats
from scipy.stats import shapiro
mu =2.6
shapiro(cats['Bwt'])
ShapiroResult(statistic=0.9518786668777466, pvalue=6.730228778906167e-05)
- mu에 2.6을 할당 후 정규성 검정 ☞ H0: 데이터가 정규분포를 따름
- 검정통계치: 0.95187
- p-value: < 0.05
- 귀무가설 기각하여 정규분포를 따르지 않음을 확인
stats.wilcoxon(cats.Bwt - mu , alternative='two-sided')
WilcoxonResult(statistic=3573.0, pvalue=0.02524520294814093)
- 데이터가 정규분포를 따르지 않으므로 wilcoxon test로 t-test 수행
- p-value < 0.05
- 귀무가설(몸무게가 2.6)을 기각
- 정규분포를 따른다면 stats.ttest_1samp(cats.Bwt, popmean=mu)
import matplotlib.pyplot as plt
cats_Bwt_cnt = pd.value_counts(cats['Bwt'].values, sort=False)
width =0.4
plt.bar(cats_Bwt_cnt.index, cats_Bwt_cnt.values,width)
plt.title('Bwt')
plt.ylabel('Count')
- 시각화 결과 또한 정규분포를 띄지 않음
3. 대응표본 T-검정 (Paired Sample t-test)
3.1 Concept
단일 모집단에 대해 어떤 실험 후 전후 평균의 차이를 비교
- 표본 내 개체들에 대해 두번의 측정 ☞ 같은 집단이므로 등분산성 만족
- 모집단의 관측값이 정규성을 만족해야함
3.2 Hypothesis
- 귀무가설: 두 모평균 사이의 차이는 없다.
- 대립가설: 두 모평균 사이의 차이는 있다.
3.3 Implementation
😗 수면제 복용의 효과 검증
import pandas as pd
data = {'before':[7,3,4,5,2,1,6,6,5,4],
'after':[8,4,5,6,2,3,6,8,6,5]}
data = pd.DataFrame(data)
stats.ttest_rel(data['after'],data['before'],alternative='greater')
TtestResult(statistic=4.743416490252569, pvalue=0.0005269356285082764, df=9)
- 표본이 정규성을 만족한다는 가정 (데이터가 임의의 데이터이므로)
data.mean()
before 4.3
after 5.3
4. 독립표본 t-test(Independent Sample t-test)
4.1 Concept
두 개의 독립된 모집단의 평균(=모평균)을 비교
- 두 모집단은 정규성을 만족해야 함
- 두 모집단의 분산이 서로 같아야 함 ☞ 등분산성
4.2 Hypothesis
- H0: 두 모평균 사이의 차이는 없다.
- H1: 두 모평균 사이의 차이는 있다.
4.3 Implementaion
😗 수컷 고양이와 암컷 고양이의 몸무게 차이 비교
import pandas as pd
cats=pd.read_csv("https://raw.githubusercontent.com/ADPclass/ADP_book_ver01/main/data/cats.csv")
female = cats.loc[cats.Sex =='F', 'Bwt']
male = cats.loc[cats.Sex =='M', 'Bwt']
stats.levene(female, male)
LeveneResult(statistic=19.43101190877999, pvalue=2.0435285255189404e-05)
- 정규성을 만족한다고 가정
- 등분산성 검정 ☞ H0: 데이터가 등분산성을 만족
- p-value < 0.05
- 등분산성을 만족하지 못하기에 equal_var=False로 독립 t-test를 수행
stats.ttest_ind(female, male, equal_var=False)
Ttest_indResult(statistic=-8.70948849909559, pvalue=8.831034455859356e-15)
print(female.mean())
print(male.mean())
2.359574468085107
2.8999999999999995
female_Bwt_cnt = pd.value_counts(female.values, sort=False)
male_Bwt_cnt = pd.value_counts(male.values, sort=False)
fig, axs = plt.subplots(1, 2,figsize=(20,5))
fig.suptitle('Bar plot')
width =0.4
axs[0].bar(female_Bwt_cnt.index, female_Bwt_cnt.values)
axs[0].set_title('female_Bwt')
axs[0].set_ylabel('Count')
axs[1].bar(male_Bwt_cnt.index, male_Bwt_cnt.values)
axs[1].set_title('male_Bwt')
axs[1].set_ylabel('Count')
plt.show()
5. ANOVA
5.1 Concept
다수의 집단을 서로 비교하고자 할 때, 집단 내의 분산, 총평균 그리고 각 집단의 평균의 차이에 의해 생긴 집단간 분산의 비교를 통해 만들어진 F분포를 이용하여 가설을 검정하는 방법
- 종속변수는 연속형
- 독립변수는 범주형
- 개수에 따라 일원, 이원, 다원 배치로 나뉨
👀 범주형 변수
- 명목형 변수: 범주 간에 순서나 등급이 없는 범주 ex) 성별, 혈액형
- 순서형 변수: 범주 간에 순서 또는 등급이 있는 변수 ex) 교육수준, 고객 만족도
5.2 분산분석 분류표
6. 일원배치 분산분석 (One-way ANOVA)
6.1 Concept
반응값에 대한 하나의 범주형 변수의 영향을 알아보기 위해 사용되는 검증 방법
- 모집단의 수에는 제한이 없으며, 각 표본의 수는 같지 않아도 됨
- F 검정 통계량 이용
- F 검정 통계량은 분산의 비율값으로, 집단 내 분산보다 집단 간 분산이 크다면 F값은 커지고 귀무가설을 기각할 확률이 높아짐
- 집단의 측정치는 서로 독립이며 정규분포를 따름
- 집단 측정치의 분산은 같음 (=등분산)
6.2 Hypothesis
- H0: k개의 집단 간 모평균에는 차이가 없다. (=같다.)
- H1: k개의 집단 간 모평균이 모두 같다고 할 수 없다.
📍 사후검정
- 집단에서 평균의 차이가 있을 경우 어떤 집단들에 대해 평균의 차이가 존재하는지 알아보는 방법
- H0: 집단들 사이의 평균은 같다.
- H1: 집단들 사이의 평균은 같지 않다.
- 던칸의 MRT, 피셔의 LSD, 튜키의 HSD
6.3 Implementation
import scipy.stats as stats
import pandas as pd
Iris_data = pd.read_csv("https://raw.githubusercontent.com/ADPclass/ADP_book_ver01/main/data/iris.csv")
Iris_data.head(100)
Iris_data["target"].unique()
array(['Iris-setosa', 'Iris-versicolor', 'Iris-virginica'], dtype=object)
Iris_data.target.value_counts()
target
Iris-setosa 50
Iris-versicolor 50
Iris-virginica 50
Name: count, dtype: int64
target_list = Iris_data["target"].unique()
setosa = Iris_data[Iris_data["target"]==target_list[0]]["sepal width"]
versicolor = Iris_data[Iris_data["target"]==target_list[1]]["sepal width"]
virginica = Iris_data[Iris_data["target"]==target_list[2]]["sepal width"]
print(target_list)
['Iris-setosa' 'Iris-versicolor' 'Iris-virginica']
import seaborn as sns
import matplotlib.pyplot as plt
# Scatter plot by Groups
sns.scatterplot(x='target',
y='sepal width',
hue='target', # different colors by group
style='target', # different shapes by group
s=100, # marker size
data=Iris_data)
plt.show()
print(stats.shapiro(setosa))
print(stats.shapiro(versicolor))
print(stats.shapiro(virginica))
ShapiroResult(statistic=0.9686915278434753, pvalue=0.20464898645877838)
ShapiroResult(statistic=0.9741329550743103, pvalue=0.3379843533039093)
ShapiroResult(statistic=0.9673907160758972, pvalue=0.18089871108531952)
- 정규성 검정 (☞ 데이터가 정규성을 띄는지)
- p-value > 0.05 이므로 정규성 만족
- 하나라도 만족하지 않으면 kruskal 고려
stats.levene(setosa,versicolor,virginica)
LeveneResult(statistic=0.6475222363405327, pvalue=0.5248269975064537)
- 등분산성 검정
- p-value > 0.05 이므로 세 집단간 분산이 동일
stats.f_oneway(setosa,versicolor,virginica)
F_onewayResult(statistic=47.36446140299382, pvalue=1.3279165184572242e-16)
- ANOVA 수행
- p-value < 0.05 이므로 귀무가설 기각 ☞ 집단간 차이 존재
from statsmodels.stats.multicomp import pairwise_tukeyhsd
from statsmodels.stats.multicomp import MultiComparison
mc = MultiComparison(data= Iris_data["sepal width"], groups=Iris_data["target"] )
tuekeyhsd = mc.tukeyhsd(alpha=0.05)
fig = tuekeyhsd.plot_simultaneous()
tuekeyhsd.summary()
- 어떤 집단간 차이가 있는지 확인하기 위해 사후 검정 수행
- 모든 p-value < 0.05이므로 귀무가설 기각
stats.kruskal(setosa,versicolor,virginica)
KruskalResult(statistic=62.49463010053111, pvalue=2.6882119006774528e-14)
- 정규성을 만족하지 못하였을 경우
import pingouin as pg
pg.welch_anova(data = Iris_data, dv ='sepal width', between='target')
- 등분산성을 만족하지 못하였을 경우
7. 이원배치 분산분석 (Two-way ANOVA)
7.1 Concept
하나의 종속변수(연속형)에 대한 두 개의 독립변수(범주형) A, B의 영향을 알아보기 위해 사용되는 검증 방법
- 두 독립변수 A,B 사이에 상관관계가 있는지를 살펴보는 교호작용을 수해야 함
- 집단의 측정치는 서로 독립이며, 정규분포를 따름
- 집단 측정치의 분산은 같음 (=등분산)
7.2 Hypothesis
📍 사후검정
- 귀무가설이 기각되었을 경우(=적어도 한 집단에서 평균의 차이가 있음), 어떤 집단들에 대해 평균의 차이가 존재하는지 알아봄
- 던칸의 MRT, 피셔의 LSD, 튜키의 HSD 방법
7.3 Implementation
😗 실린더 개수 및 변속기 종류가 주행거리에 영향을 주는지 검정
import pandas as pd
mtcars = pd.read_csv("https://raw.githubusercontent.com/ADPclass/ADP_book_ver01/main/data/mtcars.csv")
mtcars.head()
mtcars = mtcars[["mpg","am","cyl"]]
mtcars.info()
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 mpg 32 non-null float64
1 am 32 non-null int64
2 cyl 32 non-null int64
dtypes: float64(1), int64(2)
- target인 mpg는 연속형
- am과 cyl은 수치형이지만 의미상 범주형 변수임을 확인
📍가설
from statsmodels.formula.api import ols
from statsmodels.stats.anova import anova_lm
formula = 'mpg ~ C(cyl) + C(am) + C(cyl):C(am)'
model = ols(formula, mtcars).fit()
aov_table = anova_lm(model, typ=2)
aov_table
- cyl 변수와 am 변수 간의 상호작용 효과 검정
- p-value > 0.2 ☞ 교호작용 존재하지 않음 ☞ 주효과 검정이 의미있음
- cly 변수에 대한 주효과 검정
- p-vlaue < 0.05 ☞ 귀무가설 기각 ☞ 차이 존재
- am 변수에 대한 주효과 검정
- p-value > 0.05 ☞ 귀무가설 채택 ☞ 차이 없음
from statsmodels.graphics.factorplots import interaction_plot
import matplotlib.pyplot as plt
## 독립변수 cyl,am와 종속변수 mpg을 Series로 변경
cyl = mtcars["cyl"]
am = mtcars["am"]
mpg = mtcars["mpg"]
fig, ax = plt.subplots(figsize=(6, 6))
fig = interaction_plot(cyl,am, mpg,
colors=['red', 'blue'], markers=['D', '^'],
ms=10, ax=ax)
- 상호작용 그래프에서 두 선이 서로 교차시에 상호작용 존재함
- interaction_plot의 parameter는 x1, x2, y 순으로 작성
8. 교차분석(카이제곱 검정)
8.1 Concept
각 범주에 따른 결과변수의 분포를 설명하거나, 범주형 변수가 두 개 이상인 경우 상관이 있는지를 검정
- 교차표를 통해 각 셀의 관찰빈도와 기대빈도 간의 차이를 검정
- 관찰빈도: 자료로부터 얻은 빈도 분포
- 기대빈도: 두 변소가 독립일 때, 이론적으로 기대할 수 있는 빈도분포 (각 범주의 기대빈도는 5 이상)
- 적합성 검정, 독립성 검정, 동질성 검정
📍 Example
- 환자군이면서 과체중인 사람의 관찰 빈도는 25, 기대빈도는 전체의 40%인 14
- 관찰빈도와 기대빈도의 차이가 유의한 차이가 있는지를 카이제곱 통계량을 이용하여 검정
8.2 적합성 검정
8.2.1 Concept
각 범주에 따른 데이터의 빈도분포가 이론적으로 기대하는 분포를 따르는지를 검정
- ex) 주사위를 굴렸을 때, 각 주사위의 값(범주)이 1/6의 확률(빈도분포)이 맞는지 검정
8.2.2 parameters
scipy.stats.chisquare( f_obs , f_exp =None , ddof =0 , axis =0 )
- f_obs: 관찰 빈도로 pd.value_counts() 결과 값 입력
- f_exp: 각 카테고리의 기대 빈도
- doff: p-value에 대한 자유도를 조정 (k-1-ddof)
8.2.3 Implementation
😗 타이타닉호의 생존자 중 남, 녀의 비율 검정
- H0: 타이타닉호의 생존자 중 남자의 비율이 50%, 여자의 비율이 50%
- H0: 타이타닉호의 생존자 중 남자의 비율이 50%, 여자의 비율이 50%가 아님
import pandas as pd
# 데이터 불러오기
df = pd.read_csv("https://raw.githubusercontent.com/ADPclass/ADP_book_ver01/main/data/titanic.csv")
# titanic 데이터의 구조 확인
df.info()
Data columns (total 11 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 survived 891 non-null int64
1 pclass 891 non-null int64
2 sex 891 non-null object
3 age 714 non-null float64
4 sibsp 891 non-null int64
5 parch 891 non-null int64
6 fare 891 non-null float64
7 embarked 889 non-null object
8 class 891 non-null object
9 adult_male 891 non-null bool
10 embark_town 889 non-null object
dtypes: bool(1), float64(2), int64(4), object(4)
- target인 sex 변수 확인 결과 결측치가 없으며, 명목형 변수임을 확인
df_t = df[df['survived']==1]
table= df_t[['sex']].value_counts()
table
sex
female 233
male 109
- 교차분석을 위해 명목형 변수에 대한 도수분포표를 생성 ☞ 관찰빈도를 확인
from scipy.stats import chisquare
chi = chisquare(table, f_exp=[171,171])
print('<적합도 검정>\n',chi)
<적합도 검정>
Power_divergenceResult(statistic=44.95906432748538, pvalue=2.0119672574477235e-11)
- 적합도 검정 수행
- p-value < 0.05 ☞ 귀무가설 기각 ☞ 남:녀 != 50:50
8.3 독립성 검정
8.3.1 Concept
모집단이 두 개의 변수 A, B에 의해 범주화 되었을 때, 이 두 변수들 사이의 관계가 독립인지 검정
📍 Example
- 환자의 비만유무와 질환 유무가 주어졌을 때, 비만에 따른 질환 비율에 차이가 존재하는지 검정
8.3.2 Parameters
scipy.stats.chi2_contingency((observed, correction=True, lambda_=None ))
- observed: 관찰빈도로 pd.crosstab 결과를 입력
- expected: 수행 결과로 테이블 합계를 기반으로 한 기대빈도
8.3.3 Implementation
😗 타이타닉 데이터에서 좌석등급과 생존여부가 서로 독립인지 검정
- H0: 두 변수는 독립
- H1: 두 변수는 독립이 아님
df = pd.read_csv("https://raw.githubusercontent.com/ADPclass/ADP_book_ver01/main/data/titanic.csv")
table = pd.crosstab(df['class'], df['survived'])
table
- 독립 검정을 위해 crosstab(교차표) 생성
from scipy.stats import chi2_contingency
chi, p, df, expect = chi2_contingency(table)
print('Statistic:', chi)
print('p-value:', p)
print('df:', df)
print('expect: \n', expect)
Statistic: 102.88898875696056
p-value: 4.549251711298793e-23
df: 2
expect:
[[133.09090909 82.90909091]
[113.37373737 70.62626263]
[302.53535354 188.46464646]]
- 독립성 검정 수행
- p-value < 0.05 ☞ 귀무가설 기각 ☞ 독립이 아님
8.4 동질성 검정
모집단이 임의의 변수에 따라 R개 속성으로 범주화 되었을 때, R개의 부분 모집단에서 추출한 표본이 C개의 범주화된 집단의 분포가 서로 동일한지 검정
- 독립성 검정과 계산 법 및 방법이 동일
- 가설 설정만 다름
- H0: class의 분포는 survived에 관계없이 동일
- H1: class의 분포는 survived에 관계없이 동일하지 않음
댓글남기기