통계

One Sample t-test

지야소이 2023. 6. 12. 15:28

😸 단일 표본 t-test란?

: 통계적 가설 검정 방법 중 하나로, 주어진 표본의 평균이 특정한 값과 유의하게 다른지 검정하는데 사용합니다.

   z-test와 가장 큰 차이점은 모수의 표준편차를 모르고, 샘플의 표준편차를 여러번 구해서 모수의 표준편차를 추정하는 것입니다. 

  •  t값

 

 

첫번째, 예시를 들어 설명하겠습니다.

- 블랙 체리나무 31그루의 둘레(Girth), 높이(Height), 부피(Volume)의 데이터가 있다. 이 표본의 평균이 모평균과 일치하는지 단일표본 t-검정(One Sample t-test)을 통해 구하라.

- 이 때 가설은 귀무가설은 ' 높이 평균은 75이다.', 대립가설은 ' 높이 평균은 75가 아니다.' 

- 단, 데이터의 각 변수들은 정규 분포를 만족한다고 가정한다.

- 문제 1: 표본 평균 X를 구하시오. (반올림하여 소숫점 둘째자리까지 계산)

- 문제 2: 위의 가설을 검정하기 위한 검정통계량을 구하시오. (반올림하여 소숫점 둘째자리까지 계산)

- 문제 3: 위의 통계량에 대한 p값을 구하고 ((반올림하여 소숫점 넷째자리까지 계산), 가설검정의 결과를 선택하시오.

 

 

# 데이터 불러오기
import pandas as pd
df = pd.read_csv('./data/trees.csv')
df.head()

 

👉 문제 1 : 표본 평균 X를 구하시오.

result = df['Height'].mean()
round(result, 2)

> 76.0

 

👉 문제 2 : 위의 가설을 검정하기 위한 검정통계량을 구하시오. 

from scipy import stats
from math import sqrt

t_score, p_value = stats.ttest_1samp(df['Height'], popmean=75)
print('t_score:', round(t_score, 2))
print('p_value:', round(p_value, 2))

> t_score : 0.87 
  p_value : 0.39

 

👉 문제 3 : 위의 통계량에 대한 p값을 구하고, 가설검정의 결과를 선택하시오.

print('p_value:', round(p_value, 4))

> p_value: 0.3892

⇨ p-value가 유의수준 0.05 이상이므로 대립가설을 기각하고, 귀무가설을 채택합니다. 

   따라서, 높이 평균은 75라고 볼 수 있습니다.

 

 

 

 

 

두번째, 예시를 들어 설명하겠습니다.

👉 샘플의 표준편차 구하기

import pandas as pd
df = pd.read_csv("https://raw.githubusercontent.com/ethanweed/pythonbook/main/Data/zeppo.csv")
df.head()

 

import statistics
statistics.stdev(df['grades'])

> 9.520614752375915

- 표준편차(σ)는 9.52라고 말할 수 없습니다.

- 샘플의 표준편차(σ)는 9.52라고 말할 수 있습니다.

 

 

👉 가설 검증 

  • 귀무가설 : 모집단의 평균은 100이다.
  • 대립가설 : 모집단의 평균은 100이 아니다.

- 모수의 표준편차를 모를 때, 모수의 평균과 샘플의 평균이 같은지 다른지 판단해봅시다.

import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import scipy.stats as stats

mu = 0
sigma = 1
x = np.linspace(mu - 3*sigma, mu + 3*sigma, 100)
y = 100* stats.norm.pdf(x, mu, sigma)

fig, axes = plt.subplots(1,2, figsize=(15,5))

sns.lineplot(x=x, y=y, color='black', ax=axes[0])
sns.lineplot(x=x, y=y, color='black', ax=axes[1])

axes[0].set_frame_on(False)
axes[1].set_frame_on(False)
axes[0].get_yaxis().set_visible(False)
axes[1].get_yaxis().set_visible(False)
axes[0].get_xaxis().set_visible(False)
axes[1].get_xaxis().set_visible(False)

axes[0].axhline(y=0, color='black')
axes[0].axvline(x=mu, color='black', linestyle='--')

axes[1].axhline(y=0, color='black')
axes[1].axvline(x=mu + sigma, color='black', linestyle='--')

axes[0].hlines(y=23.6, xmin= mu-sigma, xmax=mu, color='black')
axes[1].hlines(y=23.6, xmin=mu-sigma, xmax=mu, color='black')

axes[0].text(mu, 42, r'$\mu = \mu_0$', size=20, ha='center')
axes[1].text(mu + sigma, 42, r'$\mu \neq \mu_0$', size=20, ha='center')

axes[0].text(mu-sigma-0.2, 23.6, r'$\sigma= ??$', size=20, ha='right')
axes[1].text(mu-sigma-0.2, 23.6, r'$\sigma = ??$', size=20, ha='right')

 

- 전체 모수에서 일부 샘플의 평균을 구해보았습닌다.

- 전체 모수를 추정해보려면 어떻게 해야할까요?

- 만약 모수가 1000명이라면, 샘플의 수를 늘리면 좀 더 정확해질수 있습니다.

 

 

mu = 0
variance = 1
sigma = np.sqrt(variance)


x = np.linspace(-4, 4, 100)
y_norm = stats.norm.pdf(x, mu, sigma)


fig, axes = plt.subplots(1, 2, figsize=(15, 5))


# t-distribution with 2 degrees of freedom
y_t = stats.t.pdf(x, 2)
sns.lineplot(x = x, y = y_norm, color = 'black', linestyle='--', ax = axes[0])
sns.lineplot(x = x, y = y_t, color = 'black', ax = axes[0])

# t-distribution with 10 degrees of freedom
y_t = stats.t.pdf(x, 10)
sns.lineplot(x = x, y = y_norm, color = 'black', linestyle='--', ax = axes[1])
sns.lineplot(x = x, y = y_t, color = 'black', ax = axes[1])

axes[0].text(0, 0.42, r'$df = 2$', size=20, ha="center")
axes[1].text(0, 0.42, r'$df = 10$', size=20, ha="center")


#sns.despine()
axes[0].get_yaxis().set_visible(False)
axes[1].get_yaxis().set_visible(False)
axes[0].set_frame_on(False)
axes[1].set_frame_on(False)

plt.show()

 - df : 전체 샘플(N)에서 -1 : 자유도(Degrees of Freedom)

- df가 크면 분포가 이상적인 분포에 가깝다고 볼 수 있습니다.

- 즉 , 모수 대비 샘플이 크면 클수록 모수를 추정하는 정확도는 올라간다는 것을 볼 수 있습니다.

 

 

👉 테스트 

- 전제 조건 

  ① 전국 대학생의 평균 점수는  67.5이다. 

  ② 심리학 전공 대학생 20명의 평균은 ?이다.

  • 귀무가설 : 전국 대학생의 평균점수와 심리학 전공 대학생의 평균점수는 통계적으로 유의하게 같다.
  • 대립가설 : 전국 대학생의 평균점수와 심리학 전공 대학생의 평균점수는 통계적으로 유의하게 다르다. 

 

  • t- 통계량, p-value값 구하기
from scipy.stats import ttest_1samp
t, p = ttest_1samp(a = df['grades'], popmean=67.5)
t, p

> (2.25471286700693, 0.03614521878144544)

⇨ t-test의 값은 2.254이며, 절대값이 클수록 변수가 유의한 영향을 가집니다. 

   또한, p-value값이 0.05이하인 0.036으로 귀무가설을 기각, 대립가설을 채택합니다.

   따라서, 전국 대학생의 평균점수와 심리학 전공 대학생의 평균점수는 통계적으로 유의하게 다르다고 할 수 있습니다.

 

 

  • 표본의 평균, 자유도 구하기
N = len(df['grades'])
degfree = N-1
sample_mean = statistics.mean(df['grades'])
print('Sample mean:', sample_mean)
print('Degrees of freedom:', degfree)

> Sample mean : 72.3
  Degrees of freedom: 19

- 심리학 전공 대학생의 평균점수는 72.3이라 볼 수 있습니다. 

- 심리학 전공 대학생의 자유도는 19입니다. 

 

 

  • 신뢰구간 구하기
from scipy import stats

confidence_level = 0.95
degrees_freedom = len(df['grades'])-1
sample_mean = statistics.mean(df['grades'])
sample_standard_error = stats.sem(df['grades'])

confidence_interval = stats.t.interval(confidence_level, degrees_freedom, sample_mean, sample_standard_error)
confidence_interval

> (67.84421513791415, 76.75578486208585)

- 평균 72.3을 기록한 심리학 전공 대학생의 평균 점수는 전체 대학생의 평균점수 67.5(t(19) = 2.25, p<0.05, 신뢰도 95% 신뢰구간 [67.8, 76.8])보다 약간 높다고 볼 수 있습니다.