[Alex] 데이터 장인의 블로그

데이터 분석을 위한 통계(t-test) feat. python 본문

Statistic

데이터 분석을 위한 통계(t-test) feat. python

Alex, Yoon 2020. 5. 10. 13:42

t-test '쉽게' 기억하자

t-테스트 또는 't-검증'은 검증 통계량이 귀무가설 하에서 t-분포를 따르는 통계적 가설 검정이다. t-검증은 검증 통계량의 스케일링 항 값이 알려진 경우 검증 통계량이 정규 분포를 따르는 경우에 가장 일반적으로 적용된다.   

출처: 위키백과

'데이터 분석을 위한 통계분석'의 첫번째 주제로 t-test(t-검정)에 대해 기억하기 쉽게 정리하는 시간을 가져보도록 하겠습니다! 

상단의 설명대로 t-test는 t-분포(student t 분포 등 뭐시기 예전에 배웠지만 그 이야기는 무시하겠습니다) 를 활용하여 내가 세운 가설이 우연이 아닐 확률이 높은지 확인하는 과정이라 생각하시면 됩니다. 이렇게만 머릿속에 정리해두고 있는다면.. 막상 이 통계분석 방법을 써먹어야 할때 기억하기 쉽지 않겠죠!? 저는 t-test에 대해 딱 한가지만 기억하면 된다고 생각합니다. 

 

두 집단 '평균'의 차이가 통계적으로 유의미한가?

출처: https://www.analyticsvidhya.com

t-검정은 '두 집단의 차이가 유의미한가'를 확인할 때 쓰입니다. 

즉 A와 B라는 두가지 집단의 연속형인 데이터가 있다면 두 집단 각각의 평균의 차이가 있는지, 있다면 얼마나 통계적으로 '유의미'한지 확인하는 과정입니다. t-test를 실시하기 위해서는 등분산성, 정규성의 조건이 만족되어야 한다고 합니다. 

1. 정규성 

정규성의 조건은 보통 30개 데이터 이상이라면 적용된다고 여깁니다.(중심극한정리) 실제 데이터 속성에 따라 다르겠지만 보통 데이터의 Volumn이 충분히 크다면 정규성 조건을 충족한다 생각하고 t-test를 진행합니다. 보통 현재의 우리가 수집하는 데이터들의 수가 충분히 크다면 (1만개 10만개..) 정규성의 조건을 충족한다 가정하고 분석을 진행하기도 합니다. 

  • 사이파이 에서 제공하는 정규성검정 명령어

    • 콜모고로프-스미르노프 검정(Kolmogorov-Smirnov test) : scipy.stats.ks_2samp
    • 샤피로-윌크 검정(Shapiro–Wilk test) : scipy.stats.shapiro
    • 앤더스-달링 검정(Anderson–Darling test) : scipy.stats.anderson
    • 다고스티노 K-제곱 검정(D'Agostino's K-squared test) : scipy.stats.mstats.normaltest
  • StatsModels에서 제공하는 정규성검정 명령어

    • 콜모고로프-스미르노프 검정(Kolmogorov-Smirnov test) : statsmodels.stats.diagnostic.kstest_normal
    • 옴니버스 검정(Omnibus Normality test) : statsmodels.stats.stattools.omni_normtest
    • 자크-베라 검정(Jarque–Bera test) : statsmodels.stats.stattools.jarque_bera
    • 릴리포스 검정(Lilliefors test) : statsmodels.stats.diagnostic.lillifors

출처: 9.5 사이파이를 사용한 검정

2. 등분산성 

등분산성 조건을 충족하는지 확인하기 위해서는 바틀렛(bartlett), 플리그너(fligner), 레빈(levene) 검정을 주로 사용합니다. 또한 등분산성 조건을 충족하지 못하게 되더라도 t-test를 사용할 수 있습니다. 

  • 사이파이 에서 제공하는 등분산검정 명령어
    • 바틀렛 검정(bartlett) : scipy.stats.bartlett
    • 플리그너 검정(fligner) : scipy.stats.fligner
    • 레빈 검정(levene) : scipy.stats.levene

출처: 9.5 사이파이를 사용한 검정

한 음식점의 매출데이터를 활용하여 t-test를 진행해보겠습니다!

sales.csv
0.01MB

1. 데이터를 불러옵니다. 

import pandas as pd

data = pd.read_csv("sales.csv", dtype = {'YMD' : 'object'})
data.head(10)
 
  YMD AMT CNT
0 20190514 0 1
1 20190519 18000 1
2 20190521 50000 4
3 20190522 125000 7
4 20190523 222500 13
5 20190524 209000 12
6 20190525 302000 18
7 20190526 267000 13
8 20190527 274000 13
9 20190528 179500 11

 

2. weather 데이터를 불러옵니다. (공공 데이터 api 기준) 

날씨 데이터는 2020/04/25 - [데이터 분석을 위한 Python] - 데이터 분석을 위한 Python < 공공데이터 api 크롤링 > 을 참고하시면 직접 얻을 수 있습니다. 

weather.csv
0.03MB
wt = pd.read_csv("weather.csv")
wt.head(10)
 
  stnId tm avgTa minTa maxTa sumRn maxWs avgWs ddMes
0 108 2018-06-01 23.8 17.5 30.2 0.0 4.3 1.9 0.0
1 108 2018-06-02 23.4 17.6 30.1 0.0 4.5 2.0 0.0
2 108 2018-06-03 24.0 16.9 30.8 0.0 4.2 1.6 0.0
3 108 2018-06-04 22.6 18.9 27.5 0.0 4.4 1.9 0.0
4 108 2018-06-05 23.7 17.7 29.2 0.0 4.0 1.7 0.0
5 108 2018-06-06 23.0 18.4 27.9 0.0 4.0 2.0 0.0
6 108 2018-06-07 22.2 17.8 29.4 0.0 4.1 2.0 0.0
7 108 2018-06-08 21.9 18.5 27.0 0.0 3.7 2.1 0.0
8 108 2018-06-09 23.7 18.9 30.1 0.5 3.5 1.4 0.0
9 108 2018-06-10 21.3 18.3 24.9 0.5 2.9 1.4 0.0

 

3. sales 데이터의 날짜를 기준으로 data를 join 하기위해 데이터 변환을 해줍니다. 2018-06-10 -> 20180610

wt.tm = wt.tm.map(lambda x : x.replace('-', ''))

 

4. 이후 두 데이터를 Join으로 결합합니다. ( 본 데이터 : 왼쪽 , 추가 데이터: 오른쪽 ) : LEFT JOIN

DF = data.merge(wt, how='left', left_on = 'YMD', right_on = 'tm')
DF.head(10)
 
  YMD AMT CNT stnId tm avgTa minTa maxTa sumRn maxWs avgWs ddMes
0 20190514 0 1 108 20190514 19.6 12.9 26.9 0.0 4.1 1.6 0.0
1 20190519 18000 1 108 20190519 19.4 17.9 21.6 22.0 2.7 1.2 0.0
2 20190521 50000 4 108 20190521 17.2 11.7 23.8 0.0 5.9 2.9 0.0
3 20190522 125000 7 108 20190522 19.5 12.3 26.5 0.0 5.4 2.4 0.0
4 20190523 222500 13 108 20190523 22.1 15.0 29.2 0.0 3.5 1.7 0.0
5 20190524 209000 12 108 20190524 24.2 16.2 33.4 0.0 4.1 1.7 0.0
6 20190525 302000 18 108 20190525 23.4 18.4 28.6 0.0 4.2 1.6 0.0
7 20190526 267000 13 108 20190526 24.5 18.6 31.1 0.0 4.5 1.8 0.0
8 20190527 274000 13 108 20190527 17.8 14.3 22.3 7.1 5.3 2.4 0.0
9 20190528 179500 11 108 20190528 18.1 11.9 24.6 0.0 4.9 2.6 0.0
 

5. 분석하고자 하는 데이터만 추출합니다.

data = DF.iloc[:,[0,2,7,8]]
data.head()
  YMD CNT maxTa sumRn
0 20190514 1 26.9 0.0
1 20190519 1 21.6 22.0
2 20190521 4 23.8 0.0
3 20190522 7 26.5 0.0
4 20190523 13 29.2 0.0

 

독립표본 t검정(Independent two-sample t-Test)

가장 많이 쓰이는 경우 입니다. A와 B 집단의 평균의 차이가 유의미한지 확인할때 독립표본 t검정을 실시합니다.

위 데이터에서 강수 여부에 따른 CNT(매출건수)의 평균 차이가 유의미한지 살펴보겠습니다. 

 

강수O : 1 강수X : 0

 data['rain_yn'] = (data.sumRn > 0).astype(int)
data
 
  YMD CNT maxTa sumRn rain_yn
0 20190514 1 26.9 0.0 0
1 20190519 1 21.6 22.0 1
2 20190521 4 23.8 0.0 0
3 20190522 7 26.5 0.0 0
4 20190523 13 29.2 0.0 0
... ... ... ... ... ...
323 20200424 51 14.3 0.0 0
324 20200425 34 17.1 0.0 0
325 20200426 55 19.0 0.0 0
326 20200427 45 18.3 0.0 0
327 20200428 45 19.9 0.0 0
import matplotlib.pyplot as plt
import numpy as np
from scipy import stats
 

비가 올때의 매출건수(손님의 방문횟수)와 안올때의 매출건수를 비교하기 위해 BOX PLOT으로 나타냅니다. 

sp = np.array(data.iloc[:,[1,4]])
tg1 = sp[sp[: , 1]==0,0]
tg2 = sp[sp[: , 1]==1,0]
plot_sp= [tg1, tg2]
ax = plt.boxplot(plot_sp)
plt.show()
 

아직까진 눈에띄는 차이가 보이지 않습니다. 

 

정규성 검정을 위해 각각 데이터의 개수를 체크합니다. (N>30)

data.groupby('rain_yn').count()
 
  YMD CNT maxTa sumRn
rain_yn        
0 236 236 236 236
1 92 92 92 92
 

아래 검정들을 수행해보니 등분산 조건을 충족하는 것으로 보여집니다. 

# 등분산 검정
print(stats.levene(tg1, tg2))
print(stats.fligner(tg1, tg2))
print(stats.bartlett(tg1, tg2))
LeveneResult(statistic=1.29079232078433, pvalue=0.2567364920691994)
FlignerResult(statistic=1.5465770819238722, pvalue=0.21364146849597607)
BartlettResult(statistic=1.770645398594986, pvalue=0.1833022260487283)
 

이제 T-TEST를 수행해줍니다. (등분산 조건 충족)

stats.ttest_ind(tg1, tg2, equal_var=True) 
Ttest_indResult(statistic=-0.19646113794791722, pvalue=0.8443716618894902)

 

해석: 

정규성, 등분산성 조건은 충족했습니다.

하지만 T-검정을 수행해보니 유의확률이 0.84로 유의수준(0.05)이상이므로 귀무가설이 기각되지 못하였으므로 A,B (강수여부)에 따른 매출건수의 평균의 차이는 없다고 보여집니다. 

 

대응표본 t검정(Paired two-sample t-Test)

두 집단의 표본이 1대1 대응하는 경우, 사용됩니다. 즉 한국초등학교 1학년 애들이 4월에 중간고사를 한번 치르고 이후 전부 EBS 인터넷 강의로 대체한 이후, 기말고사를 치르게 되면 A(중간고사)점수 = B(기말고사)점수 1대1로 대응될 것입니다. 이런 경우의 평균의 차이가 유의미한지 (성적이 올랐는지, 떨어졌는지) 대응표본 T검정으로 살펴볼 수 있습니다. 

같은 집단의 전후 데이터의 평균의 차이가 유의미한지.

단일표본 t검정(One-sample t-Test)

내가 기댓값(ex. 모수의 평균)을 아는 경우 집단의 평균의 차이와 비교합니다. 

한국고등학교 1학년 8반 애들의 수학 시험 점수 평균이 86.3점이라고 가정해봅시다. 내가 한국고등학교 1학년 수학시험 점수의 평균이 89점이라고 아는 상황이라면 이 점수를 활용하여 모집단의 평균과 차이가 있는지 확인해볼 수 있습니다. 

이런 경우 단일표본 T검정을 활용합니다. 

반응형
Comments