독립 표본 t검정 기초개념
.
Data_Preprocessing_TIL(20210626)
[학습자료]
패스트캠퍼스 온라인 강의 “파이썬을 활용한 데이터 전처리 Level UP 올인원 패키지 Online.” 를 공부하고 정리한 내용입니다.
URL : https://fastcampus.co.kr/data_online_preprocess
[학습내용]
-
독립 표본 t검정의 목적 : 서로 다른 두 그룹의 데이터 평균을 비교하는 가설검정 기법
-
영가설과 대립가설
영가설은 서로다른 두 그룹의 데이터 평균이 같다.
대립가설은 서로다른 두 그룹의 데이터 평균이 같지 않다.
지점 A의 평균이 200이고 지점 B의 평균이 180이라고 한다면 디 두지점의 평균의 차이가 유의한 차이인지 아니면 단순한 우연에 의한 차이인지를 알고 싶은 것이다.
- 독립 표본 t검정을 하기 위한 선행조건
1) 독립성 : 두 그룹은 서로 독립적이어야 한다.
한 그룹의 평균이 다른 그룹의 평균에 영향을 주지 않는 확률적으로 독립이어야 한다.
2) 정규성 : 전체 데이터는 정규분포를 따라야 한다.
정규성을 따르지 않으면 비모수 검정인 Mann-Whitney 검정을 수행해야 한다.
3) 등분산성 : 두 그룹의 데이터에 대한 분산이 같아야 한다.
두 그룹의 분산이 다르면 평균이 차이가 있다, 같다라고 했을때 분산의 영향을 받기 때문이다. 만약에 한 그룹의 분산은 매우크고, 다른 한 그룹의 분산은 매우 작다면 그런데 두 그룹의 차이가 유의하지 않다(평균이 비슷하다)고 가정해보자. 이거는 단순히 한쪽의 분산이 커서 평균이 같을 수 있기 때문이다.
Levene의 등분산 검정 : p-value가 0.05 미만이면 분산이 다르다고 판단
분산이 같을때 사용하는 통계량이 있고, 분산이 다를때 사용하는 통계량이 있다. 즉 분산이 같은지 여부에 따라서 사용하는 통계량이 다르다 라는 것만 알고가자.
통계량의 분자에는 두 그룹의 평균차이가 들어가고, 분모에는 어떤 분산이 들어가는 형태이다. 만약에 두 그룹의 평균차이가 완전히 같다라고 하면 0에 가까워질 것이고, 차이가 크면 클수록 t의 절대값이 커질 것이다.
- python을 이용한 독립표본 t검정
1) 정규성 검정(Kolmogorov-Smornov 검정)
코드
scipy.stats.kstest(x,'norn')
결과해석
pvalue가 특정수치(0.05) 미만이면 정규성을 따른다고 판단
2) 등분산성 검정(Levene test)
코드
# s1, s2, s3, s4, ... : 배열형태의 샘플데이터
# 독립표본 t검정을 할경우에는 실질적으로 s1과 s2까지만 파라미터로 들어갈 것이다.
scipy.stats.levene(s1,s2,s3,s4,...)
결과해석
pvalue가 특정수치(0.05) 미만이면 샘플간 분산이 같지 않다고 판단
3) 독립표본 t검정
코드
# a,b : 배열형태의 두 그룹의 데이터
# equal_var : 등분산성 검정에서 등분산성을 만족하는지 여부 (True 또는 False)
scipy.stats.ttest_ind(a,b,equal_var)
결과해석
statistics가 양수면 a의 평균이 더 크다고 판단
pvalue가 특정수치 미만이면 a와 b의 평균이 같지 않다고 판단
4) Mann-Whitneyu 검정 (정규성 검정을 만족하지 않을때 사용하는 검정)
코드
# a,b : 배열형태의 두 그룹의 데이터
scipy.stats.mannwhitneyu(a,b)
result=(statistics,pvalue)
의 튜플형태
pvalue가 특정수치 미만이면 a와 b의 평균이 같지 않다고 판단
- python을 이용한 실제 실습
반별로 점수차이가 있는지 독립표본 t검정으로 검증을 해보자
step 1) 데이터 load
# data 불러오기
import os
import pandas as pd
# pwd 시 경로 : /c/Users/user/Desktop/aa/2. 탐색적 데이터 분석/데이터
os.chdir(r"C:/Users/user/Desktop/aa/2. 탐색적 데이터 분석/데이터/")
df1 = pd.read_csv("반별_점수_type1.csv", engine = "python")
df1
반 | 점수 | |
---|---|---|
0 | A | 73 |
1 | A | 69 |
2 | A | 71 |
3 | A | 71 |
4 | A | 73 |
5 | A | 67 |
6 | A | 73 |
7 | A | 69 |
8 | A | 62 |
9 | A | 74 |
10 | A | 68 |
11 | A | 66 |
12 | A | 70 |
13 | A | 82 |
14 | A | 70 |
15 | A | 65 |
16 | A | 76 |
17 | A | 73 |
18 | A | 58 |
19 | A | 81 |
20 | B | 63 |
21 | B | 56 |
22 | B | 73 |
23 | B | 61 |
24 | B | 55 |
25 | B | 77 |
26 | B | 75 |
27 | B | 65 |
28 | B | 61 |
29 | B | 55 |
group_A = df1['점수'].loc[df1['반'] == 'A'].values
group_B = df1['점수'].loc[df1['반'] == 'B'].values
print(type(group_A))
print(group_A)
print(group_B)
<class 'numpy.ndarray'>
[73 69 71 71 73 67 73 69 62 74 68 66 70 82 70 65 76 73 58 81]
[63 56 73 61 55 77 75 65 61 55]
step 2) load 한 데이터에 대한 정규성 검정
# kstest를 이용한 정규성 검정: 모두 정규 분포를 띔을 확인
from scipy.stats import *
print(kstest(group_A, 'norm'))
print(kstest(group_B, 'norm'))
KstestResult(statistic=1.0, pvalue=0.0)
KstestResult(statistic=1.0, pvalue=0.0)
step 3) load 한 데이터에 대한 등분산성 검정
# 등분산 검정
levene(group_A, group_B)
# pvalue가 0.05 미만이 아니므로, 등분산을 띈다고 볼 수 있음
LeveneResult(statistic=2.033067087400979, pvalue=0.164964086222101)
import numpy as np
np.var(group_A, None, ddof=1) # 분산이 32.26으로 나온다
32.26052631578948
step 4) 독립표본 t검정 실시
# A와 B간에는 차이가 존재함을 확인
print(ttest_ind(group_A, group_B, equal_var = True))
Ttest_indResult(statistic=2.5128526794964134, pvalue=0.01801095352893767)
p-value가 0.018로 0.05보다 작기 때문에 그룹a와 그룹b의 유의미한 차이가 존재한다고 볼 수 있다. 그리고 statistics가 양수인걸로 보아 그룹a가 그룹b보다 성적이 좋겠다라고 판단할 수 있다.
Tip. 다른 포맷의 데이터 처리
a반은 전부 양수인데 b반은 .0이 붙어있는 것을 볼 수 있다. 왜 두반의 포맷이 다를지 생각할 수 있는데 이는 b반에 결측값이 있기 때문이다. 왜냐하면 NaN값의 경우에는 type이 float이기 때문이다. 아래에 데이터를 확인해봐도 알 수 있다.
df2 = pd.read_csv("반별_점수_type2.csv", engine = "python")
df2
A반 | B반 | |
---|---|---|
0 | 73 | 63.0 |
1 | 69 | 56.0 |
2 | 71 | 73.0 |
3 | 71 | 61.0 |
4 | 73 | 55.0 |
5 | 67 | 77.0 |
6 | 73 | 75.0 |
7 | 69 | 65.0 |
8 | 62 | 61.0 |
9 | 74 | 55.0 |
10 | 68 | NaN |
11 | 66 | NaN |
12 | 70 | NaN |
13 | 82 | NaN |
14 | 70 | NaN |
15 | 65 | NaN |
16 | 76 | NaN |
17 | 73 | NaN |
18 | 58 | NaN |
19 | 81 | NaN |
# 길이가 달라서 결측이 발생할 수 있으므로,
# 일반적으로는 결측을 제거한 뒤 각 컬럼을 group_A와 group_B에 저장해야 한다.
group_A = df2['A반'].dropna().values
group_B = df2['B반'].dropna().values
# kstest를 이용한 정규성 검정: 모두 정규 분포를 띔을 확인
from scipy.stats import *
print(kstest(group_A, 'norm'))
print(kstest(group_B, 'norm'))
KstestResult(statistic=1.0, pvalue=0.0)
KstestResult(statistic=1.0, pvalue=0.0)
# 등분산 검정
levene(group_A, group_B)
# pvalue가 0.05미만이 아니므로, 등분산을 띈다고 볼 수 있음
LeveneResult(statistic=2.033067087400979, pvalue=0.164964086222101)
import numpy as np
np.var(group_A, None, ddof=1)
32.26052631578948
# A와 B간에는 차이가 존재함을 확인
print(ttest_ind(group_A, group_B, equal_var = True))
Ttest_indResult(statistic=2.5128526794964134, pvalue=0.01801095352893767)