데이터 분석 초보자를 위한 T-test & Chi-squared test

Gayeon Kim·2020년 9월 18일
16

데이터 분석

목록 보기
3/9

1. 어떤 가설 검정 방법을 선택해야 할지 몰라 혼란스러운 당신에게


통계학을 한 번이라도 공부한 적이 있다면 T-test, Chi-squared test, Z-test 등에 대해서 들어봤을 것이다. 이것들은 모두 가설 검정 방법이다. 먼저 가설 검정이 무엇인지 간단히 정리해보자. 가설 검정이란 어떤 주장이 맞는지 틀리는지 확인하는 과정이다. 예를 들어, 지금 당신의 손에 주사위 하나가 있다고 치자. 우리는 주사위가 1부터 6까지 골고루 나온다고 알고 있다. 하지만 과연 당신의 손에 있는 주사위도 그럴까? 혹시 그 주사위는 무게 중심이 달라서 1이 제일 많이 나오고 6은 아예 안 나오지는 않을까? 당신은 주사위가 공평한 주사위인지 의심이 들었고, 한 번 확인해보기로 했다. 이럴 때 사용하는 게 바로 가설 검정이다. "이 주사위는 공평한 주사위이다."라는 가설을 세우고, 주사위를 n번 던진 뒤 관측값을 바탕으로 가설을 채택할지(주사위가 공평하다), 아니면 기각할지(주사위가 공평하지 않다)를 결정한다.

가설 검정을 할 때는 검정하고자 하는 가설에 따라 다른 방법이 사용된다. 무슨 방법을 쓰든 결과는 '가설이 맞다.' 아니면 '가설이 틀리다.' 일 텐데 왜 각기 다른 방법을 사용하냐고? 가설 검정 방법은 일종의 도구이다. 우리는 요리를 할 때 목적에 맞는 도구를 선택하여 사용한다. 식자재를 자르기 위해서는 칼을 사용하고, 음식을 끓이기 위해서는 냄비를 사용한다. 또 음식에 짠맛을 더하기 위해서는 소금을 사용하고, 단맛을 더하기 위해서는 설탕을 사용한다. 이렇게 각 도구마다 기능이 정해져 있으며, 목적에 맞게 적절한 도구를 선택하여 사용한다. 가설 검정 방법을 선택하는 것도 이와 같다. 각 가설 검정 방법은 각자가 검정할 수 있는 가설의 형태가 미리 정해져 있으며, 우리는 이를 임의로 바꿀 수 없다. 파를 썰고 싶은데 소금을 사용한다든지, 음식에 짠 맛을 더하고 싶은데 냄비를 사용하지는 않는 것처럼 말이다. 다시 말해서, 우리가 검정하고 싶은 가설의 형태에 따라서 해당 가설을 검정해줄 수 있는 알맞은 도구를 선택해야 한다.

오늘은 이 도구 중에 대표적인 두 가지 방법인 T-test와 Chi-squared test에 대해서 알아보자.



데이터 준비하기


# 필요한 패키지 import
import pandas as pd
import numpy as np
import seaborn as sns
from scipy import stats

# 데이터셋 불러오기
df = sns.load_dataset("penguins")
df = df.dropna()

# 데이터 프레임 column명 수정
df = df.rename(columns={"species":"species", "island":"island", "bill_length_mm":"bill_length", "bill_depth_mm":"bill_depth",
                        "flipper_length_mm":"flipper_length", "body_mass_g":"body_mass", "sex":"sex"})

penguins 데이터셋은 아래와 같은 정보를 담고 있다.

  • species : 펭귄의 종 (Adelie, Chinstrap, Gentoo)
  • island: 살고 있는 섬 이름 (Torgersen, Dream, Biscoe)
  • bill_length: 부리의 길이 (단위: mm)
  • bill_depth: 부리의 깊이 (단위: mm)
  • flipper_length: 플리퍼(≒ 날개)의 길이 (단위: mm)
  • body_mass: 체질량 (단위: g)
  • sex: 성별 (MALE, FEMALE)

지금부터 이 penguins 데이터셋에 있는 데이터들은 전체 펭귄(모집단)을 대표하는 표본집단이라고 생각하자.



2. T-test (스튜던트 t 검정)


T-test는 표본집단의 평균을 비교하고 싶을 때 선택하는 방법이다. T-test는 sample의 개수에 따라 one-sample T-test와 two sample T-test로 나뉘며, 귀무가설이 비슷하면서도 조금 다르다.

1) one sample T-test

Adelie 펭귄은 키가 약 70cm까지 자라는 펭귄이라고 한다. 이 말을 들은 당신의 머릿속에는 "키가 그 정도면 몸무게는 8kg 정도 될 것 같아"라는 생각이 들었다. 이러한 당신의 생각이 맞는지 확인하고 싶을 때 사용하는 것이 바로 one-sample T-test이다. one-sample T-test는 표본집단의 평균이 특정 값인지 추정할 때 사용한다. "Adelie 펭귄의 평균 몸무게는 8kg일 것이다"를 검정할 때에 가설은 아래와 같다.

  • 귀무가설: Adelie 펭귄의 평균 몸무게는 8kg일 것이다.
  • 대립가설: Adelie 펭귄의 평균 몸무게는 8kg이 아닐 것이다.
  • 신뢰도: 95%
adelie = df[df["species"] == "Adelie"]["body_mass"]
stats.ttest_1samp(adelie, 8000) # 단위: g

[Out]

Ttest_1sampResult(statistic=-113.12763925848728, pvalue=2.511309970725206e-143)

one sample T-test 시행 결과, p-value가 0.05보다 작기 때문에 귀무가설을 기각하고 대립가설을 채택한다. 따라서 Adelie 펭귄의 평균 몸무게는 8kg이 아니다.


이번에는 아래와 같이 가설을 세우고 one sample T-test를 한 번 해보자.

  • 귀무가설: Adelie 펭귄의 평균 몸무게는 3.72kg일 것이다.
  • 대립가설: Adelie 펭귄의 평균 몸무게는 3.72kg이 아닐 것이다.
  • 신뢰도: 95%
adelie = df[df["species"] == "Adelie"]["body_mass"]
stats.ttest_1samp(adelie, 3720)

[Out]

Ttest_1sampResult(statistic=-0.36452038810359905, pvalue=0.7160005111390735)

one sample T-test 시행 결과, p-value가 0.05보다 크기 때문에 귀무가설을 기각할 수 없다. 따라서 Adelie 펭귄의 평균 몸무게는 3.72kg이다.

이렇게 one sample T-test의 귀무가설은 "표본집단의 평균은 n이다."로 정해져 있다. 이에 대한 대립가설은 "표본집단의 평균은 n이 아니다."이다. 그리고 신뢰도가 95%라는 전제하에 p-value가 0.05보다 작으면 귀무가설을 기각하고 대립가설을 채택하며, 0.05보다 크면 귀무가설을 기각할 수 없다.


2) two sample T-test

two sample T-test도 표본집단의 평균을 비교한다는 점에서는 one sample T-test와 동일하다. 다만, one sample T-test는 해당 표본집단의 평균과 특정한 값을 비교할 때 쓴다면, two sample T-test는 표본집단 A와 표본집단 B의 평균을 비교할 때 사용한다.

Adelie 펭귄은 Gentoo 펭귄 속의 펭귄 종이라고 한다. 그렇다면 Adelie 펭귄과 Gentoo 펭귄의 생김새가 비슷하지 않을까? Adelie 펭귄과 Gentoo 펭귄의 평균 부리 깊이가 같은지 아래처럼 two sample T-test를 시행하여 확인해보자.

  • 귀무가설: Adelie 펭귄의 평균 부리 깊이와 Gentoo 펭귄의 평균 부리 깊이는 같다.
  • 대립가설: Adelie 펭귄의 평균 부리 깊이와 Gentoo 펭귄의 평균 부리 깊이는 같지 않다.
  • 신뢰도: 95%
adelie = df[df["species"] == "Adelie"]["bill_depth"]
gentoo = df[df["species"] == "Gentoo"]["bill_depth"]
stats.ttest_ind(adelie, gentoo)

[Out]

Ttest_indResult(statistic=24.208855744860315, pvalue=6.91055572279657e-69)

two sample T-test 시행 결과, p-value가 0.05보다 작기 때문에 귀무가설을 기각하고 대립가설을 채택한다. 따라서 Adelie 펭귄의 평균 부리 깊이와 Gentoo 펭귄의 평균 부리 깊이는 같지 않다.

그럼 이번에는 Adelie 펭귄의 평균 부리 깊이와 Chinstrap 펭귄의 평균 부리 깊이가 같은지 확인해보자.

  • 귀무가설: Adelie 펭귄의 평균 부리 깊이와 Chinstrap 펭귄의 평균 부리 깊이는 같다.
  • 대립가설: Adelie 펭귄의 평균 부리 깊이와 Chinstrap 펭귄의 평균 부리 깊이는 같지 않다.
  • 신뢰도: 95%
adelie = df[df["species"] == "Adelie"]["bill_depth"]
chinstrap = df[df["species"] == "Chinstrap"]["bill_depth"]
stats.ttest_ind(adelie, chinstrap)

[Out]

Ttest_indResult(statistic=-0.41849509118137584, pvalue=0.6760088132938111)

two sample T-test 시행 결과, p-value가 0.05보다 크기 때문에 귀무가설을 기각할 수 없다. 따라서 Adelie 펭귄의 평균 부리 깊이와 Chinstrap 펭귄의 평균 부리 깊이는 같다.

위와 같이 two sample t-test의 귀무가설은 "두 표본집단의 평균이 같다."로 정해져 있다. 이에 대한 대립가설은 "두 표본집단의 평균이 같지 않다."이다. 그리고 one sample t-test에서 그랬던 것처럼, 신뢰도가 95%라는 전제하에 p-value가 0.05보다 작으면 귀무가설을 기각하고 대립가설을 채택하며, 0.05보다 크면 귀무가설을 기각할 수 없다.

사실 Adelie 펭귄의 평균 몸무게를 정확히 구해보면 3.72kg이 아니라 약 3.706kg이 나온다. 그리고 Adelie 펭귄의 평균 부리 깊이는 18.35mm이고, Chinstrap 펭귄의 평균 부리 길이는 15mm로 차이가 있다. 그럼 T-test 결과가 틀린 게 아니냐고? T-test가 한 표본집단의 평균이 특정 값과 같은지 혹은 두 표본집단의 평균이 같은지 추정하는 테스트인 건 맞다. 그러나 두 값이 정확하게 같은지 확인하는 게 아니라 두 값 사이에 통계적으로 유의미한 차이가 있는지 추정하는 테스트이다. 즉, T-test 결과에 따르면 Adelie 펭귄의 평균 몸무게는 3.72kg라고 봐도 무방하고, Adelie 펭귄과 Chinstrap 펭귄의 평균 부리 깊이는 같다고 봐도 무방하다. 값이 완벽하게 같은지를 보는 게 아니라 '통계적으로 유의미한 차이가 있는지 추정한다'는 것은 T-test뿐만 아니라 아래 나올 Chi-squared test를 비롯한 다른 가설 검정 방법에서도 동일하다.



3. Chi-squared test (카이제곱 검정)


T-test는 표본집단의 평균을 비교할 때 선택하는 방법이었다면, Chi-squared test는 표본집단의 분포를 비교할 때 선택하는 방법이다. 다만, Chi-squared test는 categorical data에 대해서만 사용이 가능하다. Chi-squared test도 sample의 개수에 따라 one-sample Chi-squared test와 two sample Chi-squared test로 나뉜다.

1) one sample Chi-squared test

one sample Chi-squared test은 서론에서 말했던 "이 주사위는 공평한 주사위이다."에 대한 검정처럼, 데이터의 분포가 예상과 같은지 확인할 때 사용한다.

우리는 흔히 암컷과 수컷의 개체 수가 동일하리라 생각한다. 따라서 만약 펭귄 표본집단에 총 100마리의 펭귄이 있다면, 성별 분포의 기댓값은 암컷과 수컷이 각각 50마리씩 있는 것이다. 그럼 one sample Chi-squared test를 통해 펭귄 표본집단의 분포가 우리의 기대와 같은지 확인해보자.

  • 귀무가설: 펭귄의 성비는 1:1일 것이다.
  • 대립가설: 펭귄의 성비는 1:1이 아닐 것이다.
  • 신뢰도: 95%
male = df["sex"].value_counts()["MALE"]
female = df["sex"].value_counts()["FEMALE"]
exp = len(df)/2
stats.chisquare(f_obs=[male, female], f_exp=[exp, exp])

[Out]

Power_divergenceResult(statistic=0.02702702702702703, pvalue=0.8694170607412391)

p-value가 0.05보다 크므로 귀무가설을 기각할 수 없다. 따라서, 펭귄의 성비는 1:1이다.

이처럼 one sample Chi-squared test의 귀무가설은 "표본집단의 분포가 기대와 동일하다."이다. 이에 대한 대립가설은 "표본집단의 분포가 기대와 동일하지 않다."이다. 그리고 신뢰도가 95%라는 전제하에 p-value가 0.05보다 작으면 귀무가설을 기각하고 대립가설을 채택하며, 0.05보다 크면 귀무가설을 기각할 수 없다.

2) two sample Chi-squared test

two sample Chi-squared test는 두 표본집단의 분포가 동일한지 확인할 때 사용한다. 즉, 두 표본집단이 연관이 있는지, 없는지를 확인할 수 있다.

펭귄의 몸무게와 플리퍼 길이는 관련이 있지 않을까? two sample Chi-squared test를 사용하면 "펭귄의 몸무게와 플리퍼 길이는 독립이다."라는 가설을 검정할 수 있다. 단, 여기서 주의해야 할 점은 Chi-squared test는 categorical data에만 사용할 수 있다는 점이다. 우리가 가지고 있는 데이터셋에서는 펭귄의 몸무게와 플리퍼 길이가 continuous data이다. 따라서 펭귄의 몸무게와 플리퍼 길이에 대한 Chi-squared test를 시행하려면 먼저 데이터를 categorical data로 바꿔줘야 한다.

mass_cut = pd.cut(df["body_mass"], 3).astype("category")
flipper_cut = pd.cut(df["flipper_length"], 3).astype("category")
data = pd.crosstab(mass_cut, flipper_cut)
data.columns = ["Short", "Middle", "Long"]
data.index = ["Light", "Middle", "Heavy"]

몸무게와 플리퍼 길이를 각각 세 그룹으로 나누고, 그 결과를 crosstab으로 만들었다. 이제 펭귄의 몸무게와 플리퍼 길이에 대해서 two sample Chi-squared test를 시행할 수 있다.

  • 귀무가설: 펭귄의 몸무게와 플리퍼 길이는 연관이 없다.
  • 대립가설: 펭귄의 몸무게와 플리퍼 길이는 연관이 있다.
  • 신뢰도: 95%
chi, pvalue, _, _ = stats.chi2_contingency(data, correction=False)
chi, pvalue

[Out]

(244.23390701043138, 1.1365768507791132e-51)

p-value가 0.05보다 작기 때문에 귀무가설을 기각하고 대립가설을 채택한다. 따라서 펭귄의 몸무게와 플리퍼 길이는 연관이 있다.

이처럼 two sample Chi-squared test의 귀무가설은 "두 변수는 연관이 없다(두 변수는 독립이다)."이다. 이에 대한 대립가설은 "두 변수는 연관이 있다(두 변수는 독립이 아니다)."이다. 그리고 신뢰도가 95%라는 전제하에 p-value가 0.05보다 작으면 귀무가설을 기각하고 대립가설을 채택하며, 0.05보다 크면 귀무가설을 기각할 수 없다.



지금까지 가설 검정 방법 중 T-test와 Chi-squared test에 대해서 알아봤다. 이 외에도 가설 검정 방법은 매우 많다. 하지만 가설 검정 방법은 저마다 고유한 기능을 가지고 있는 도구와 같다는 것은 변하지 않는다. 그러므로 오늘 T-test와 Chi-squared test를 살펴보면서 했던 것처럼, 각 검정 방법이 무엇을 확인하고자 할 때 사용하는 검정 방법인지, 귀무가설과 대립가설은 무엇인지 잘 살펴본다면 원하는 목적에 맞는 가설 검정 방법을 쉽게 선택할 수 있을 것이다.

4개의 댓글

comment-user-thumbnail
2021년 7월 16일

언니 덕분에 잘 이해했어..! 포스팅 고마워!

답글 달기
comment-user-thumbnail
2021년 7월 16일

안녕하세요 ! 짜임새 있는 글 감사합니다 !
가설은 어떤 기준으로 세우시는지 궁금해서 댓글 남깁니다 !
또 자유도는 어떻게 처리하시는 건지,, 궁금합니다. 데이터 중 검증을 위해 뽑아낸 데이터는 자유도가 1 이기 때문에 그게 디폴트로 들어가는 건가요 ?!

답글 달기
comment-user-thumbnail
2021년 8월 1일

pvalue가 0.05보다 작으면 변수간 연관이 있는건가요?

답글 달기
comment-user-thumbnail
2022년 6월 13일

깔끔한 글 너무 감사합니다!!

답글 달기