
시작하며
통계적 추론(statistical inference)이란 표본의 통계량을 이용하여 모집단의 모수에 대해 추측하는 것이다. 추정(estimation)과 가설검증(hypothesis testing)으로 구성된다. 이 포스팅에서는 모집단·표본·확률변수의 개념을 정리하고, 파이썬을 통해 구간추정과 가설검증을 실습한다.
통계적 추론의 기본 개념
모집단(Population)
정보를 얻고자 하는 전체 대상(집단)을 의미한다.
표본(Sample)
모집단 전체 집단을 알기 힘들거나 수집하는 데 비효율적이므로, 모집단을 대표해주는 부분집합을 표본(sample)이라 한다.
- 표본평균
- 중심극한정리 : 표본 크기가 충분히 커짐에 따라 정규분포로 근사한다.
# 파이썬 numpy의 확률변수 생성 함수를 활용한 중심극한정리 이해
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
np.random.seed(0) # 재생산을 위해 seed 고정
### 균등분포(uniform distribution)를 가진 모집단에서 표본평균의 분포를 보기 위해 여러 개의 표본 추출
# 하나의 표본 - 가상의 모집단
uniform_sample = np.random.uniform(0, 5, 1000)
sns.histplot(uniform_sample)
plt.title('Uniform distribution')
plt.show()
# uniform 분포에서 1000개의 표본을 생성하는 함수
def sample_u_means(low, high, sample_size):
means = np.zeros(1000)
for i in range(0, 1000):
sample = np.random.uniform(low, high, sample_size)
means[i] = sample.mean()
return means
# 표본 크기가 작은 경우 : 표본크기 = 1
sample_size = 1
low = 0
high = 5
sns.histplot(sample_u_means(low, high, sample_size))
plt.title('sample size = 1')
plt.show()
# 1000개의 표본 생성 : 표본크기 = 30
# 표본의 크기가 큰 경우는 표본평균의 분포가 정규분포와 유사함을 알 수 있음
sample_size = 30
low = 0
high = 5
sns.histplot(sample_u_means(low, high, sample_size))
plt.title('sample size = 30')
plt.show()
### 이항분포 B(5, 0.7)를 가진 모집단에서 표본평균의 분포를 보기 위해 여러 개의 표본 생성
# 하나의 표본
n = 5
p = 0.7
sample_size = 1000
binom_sample = np.random.binomial(n, p, sample_size)
sns.histplot(binom_sample)
plt.title('Binomial distribution')
plt.show()
# 이항분포에서 1000개의 표본을 생성하는 함수
def sample_means(sample_size, n, p):
means = np.zeros(1000)
for i in range(0, 1000):
sample = np.random.binomial(n, p, sample_size)
means[i] = sample.mean()
return means
# 표본 크기가 작은 경우 : 표본크기 = 3
sample_size = 3
sns.histplot(sample_means(sample_size, n, p))
plt.title('sample size = 3')
plt.show()
# 표본 크기가 큰 경우 : 표본크기 = 5000
# 표본의 크기가 큰 경우는 표본평균의 분포가 정규분포와 유사함을 알 수 있음
sample_size = 5000
sns.histplot(sample_means(sample_size, n, p))
plt.title('sample size = 5000')
plt.show()좋은 표본이란?
- 관심 있는 특성을 가진 개체들의 의식적 선택을 피해야 한다.
- 연구 목적을 얻기 위한 표본 선택을 하지 말아야 한다.
- 추출된 표본을 다른 값으로 대체하거나 결측치를 함부로 대체하지 않아야 한다.
모수(parameter)와 통계량(statistic)
모수 : 모집단의 특성을 나타내는 양적인 척도를 의미하며, 모평균·모분산 등이 있다. 통계량 : 표본에서 얻어진 특성치들로, 표본평균·표본분산 등이 있다.
확률변수(random variable)
모집단에 대해 어떤 값을 가질지에 대한 가능성을 확률로 표현한다.
- 이산형(discrete) 확률변수
- 베르누이분포
- 이항분포
- 연속형(continuous) 확률변수
- 정규분포(normal distribution) : 좌우대칭(symmetric), 하나의 피크(unimodal), 벨모양(bell-shape)
- 평균과 분산이 모양을 결정한다.
- 정규분포의 표준화를 통해 어떤 정규분포든 평균이 0이고 분산이 1인 표준정규분포로 변환이 가능하다.
- T-분포 : 좌우대칭(symmetric), 하나의 피크(unimodal), 벨모양(bell-shape) + 자유도를 가진다.
- 언제나 평균이 0이다.
- 정규분포에 비해 두꺼운 꼬리를 가진다.
- 구간추정, 평균에 대한 가설검정 등에서 활용한다.
- 정규분포(normal distribution) : 좌우대칭(symmetric), 하나의 피크(unimodal), 벨모양(bell-shape)
추정(estimation)
- 점추정(point estimation)
- 구간추정(interval estimation)
- 신뢰수준 : 참값을 구하기 위한 작업을 반복하였을 때, 참값이 구해진 구간에 포함되어 있을 비율
import pandas as pd
import numpy as np
from scipy import stats
sample = np.arange(0, 10)
sample
# 표본에서 평균과 표준오차 계산
sample_mean = np.mean(sample)
sample_se = stats.sem(sample)
print('표본평균= ', sample_mean, ', 표준오차= ', sample_se)
# 표본평균= 4.5 , 표준오차= 0.9574271077563381
# 모평균에 대한 99% 신뢰구간
confidence_level = 0.99
df = sample.size - 1
confidence_interval = stats.t.interval(confidence_level, df, sample_mean, sample_se)
print(confidence_interval)
# (1.388519354409619, 7.611480645590381) -> 모평균에 대한 99% 신뢰구간은 (1.39, 7.61)
# 모평균에 대한 95% 신뢰구간
confidence_level = 0.95
df = sample.size - 1
confidence_interval = stats.t.interval(confidence_level, df, sample_mean, sample_se)
print(confidence_interval)
# (2.3341494103866087, 6.665850589613392) -> 모평균에 대한 95% 신뢰구간은 (2.33, 6.67)로 신뢰수준이 낮아지면 구간의 크기가 작아짐
# 표본의 크기가 커지면?
sample = np.repeat(np.arange(0, 10), 5)
sample
# 표본에서 평균과 표준오차 계산
sample_mean = np.mean(sample)
sample_se = stats.sem(sample)
print('표본평균= ', sample_mean, ', 표준오차= ', sample_se)
# 표본평균= 4.5 , 표준오차= 0.41032590332414487
confidence_level = 0.95
df = sample.size - 1
confidence_interval = stats.t.interval(confidence_level, df, sample_mean, sample_se)
print(confidence_interval)
# (3.6754192266103853, 5.324580773389615)
## 아파트 실거래가 데이터 활용한 평균의 추정
import pandas as pd
apt = pd.read_excel('data/아파트_실거래가_서울.xlsx')
apt.rename(columns={'전용면적(㎡)': '면적', '거래금액(만원)': '가격'}, inplace=True)
apt['단가'] = apt.가격 / apt.면적
# 데이터에서 단가의 평균과 표준오차 계산
sample_mean = apt.단가.mean()
sample_se = apt.단가.sem()
print('표본평균= ', sample_mean, ', 표준오차= ', sample_se)
confidence_level = 0.95
df = len(apt) - 1
confidence_interval = stats.t.interval(confidence_level, df, sample_mean, sample_se)
print(confidence_interval)가설검증(hypothesis testing)
- 귀무가설(null hypothesis : H0) : 그에 반하는 충분한 근거가 나올 때까지 잠정적으로 참이라고 하는 가설
- 대립가설(alternative hypothesis : H1) : 새로운 주장이고, 실제로 입증하기를 원하는 가설
가설검증 절차:
- 귀무가설, 대립가설 설정
- 검정통계량 계산 (기존 통계학 바탕으로 수식이 이미 있음)
- 설정한 유의수준 하에서 검정통계량을 바탕으로 귀무가설 기각 여부 결정
T-Test : 모평균에 대한 가설검정. 모집단의 정규성을 가정할 수 있거나, 표본의 크기가 충분히 큰 경우 활용한다.
유의확률(p-value)
귀무가설 하에서 관찰된 통계량만큼의 극단적인 값을 가질 확률이다. 검정통계량과 임계값을 비교하여 기각 여부를 결정하는 방법과 유의확률(p-value)와 유의수준을 비교하는 방법은 결과적으로 동일하다.
두 집단의 평균 비교 : 쌍체표본 T-검정(Paired T-test)
# (예) 새로운 시스템 도입 후 12개 지역의 연간 민원 접수 건수 비교
before = [130, 133, 132, 138, 140, 128, 140, 132, 126, 130, 125, 140]
after = [120, 130, 121, 107, 132, 125, 141, 133, 118, 133, 111, 131]
import pandas as pd
dat = pd.DataFrame({'before': before, 'after': after})
dat.mean()
import matplotlib.pyplot as plt
import seaborn as sns
sns.boxplot(data=dat, showmeans=True)
plt.show()
# (예) 새로운 시스템 도입 후 20개 지역의 연간 민원 접수 건수에 차이가 나는지를 검정
# 지역에 관한 정보로 전/후 관측치가 연결되어 있고 관심은 전/후 값의 차이이므로 단일 표본의 평균 검정과 동일함 : paired t-test 고려
# (양측검정) H0 : μ_before = μ_after vs. H1 : μ_before ≠ μ_after
# paired T-test 시행
from scipy import stats
result = stats.ttest_rel(dat.before, dat.after) # (default) 양측검정
result
print("검정통계량= %.3f , p-value = %.3f" % result)
# (참고) 다른 출력 방식
t, p = result
print('양측검정 p-value : %.4f' % p)
p2 = p / 2
print('단측검정 p-value : %.4f' % p2)정리하며
통계적 추론은 표본을 통해 모집단을 이해하는 핵심 방법론이다. 중심극한정리에 따라 표본 크기가 충분히 크면 표본평균의 분포는 정규분포에 근사하므로 T-분포 기반의 구간추정과 가설검증이 가능해진다. p-value를 해석할 때는 유의수준(0.05 또는 0.01)과 비교하여 귀무가설의 기각 여부를 결정하고, 단측검정과 양측검정을 문제 상황에 맞게 선택하는 것이 중요하다.