1 개요
가설 검정을 설계할 때 핵심 질문은 “몇 명을 모아야 하는가?”다. 이 질문에 답하려면 네 가지 요소를 지정해야 한다:
| 요소 | 기호 | 의미 | 전형적 값 |
|---|---|---|---|
| 유의수준 | \(\alpha\) | Type I Error 상한 | 0.01, 0.05 |
| 검정력 | \(1 - \beta\) | 참 차이를 감지할 확률 | 0.80, 0.90 |
| 효과 크기 | \(\delta\) | 감지하고 싶은 최소 차이 | 문제 의존 |
| 분산 | \(\sigma^2\) | 측정값의 변동성 | 파일럿 연구 또는 문헌 |
이 네 요소 중 하나를 결정하려면 나머지 셋이 주어져야 한다. 실무에서는 \(\alpha\), \(1-\beta\), \(\delta/\sigma\) 를 지정하고 \(n\) 을 구한다.
Casella & Berger는 예제 8.3.4에서 단일 표본 정규 검정의 \(c\) 와 \(n\) 동시 결정 방법을 보여준다 (Casella & Berger, 2002, §8.3).
2 검정력 함수와 표본 크기의 관계
2.1 단일 표본 검정 (알려진 \(\sigma\))
\(X_1, \ldots, X_n \overset{\text{iid}}{\sim} N(\theta, \sigma^2)\), \(\sigma^2\) 알려진.
검정: \(H_0: \theta \leq \theta_0\) vs \(H_1: \theta > \theta_0\).
기각역: \(\bar{X} > \theta_0 + c \sigma/\sqrt{n}\), 즉 표준화 통계량이 \(z = (\bar{X} - \theta_0)/(\sigma/\sqrt{n}) > c\).
검정력 함수:
\[\beta(\theta) = P_\theta\!\left(Z > c + \frac{\theta_0 - \theta}{\sigma/\sqrt{n}}\right) = 1 - \Phi\!\left(c + \frac{\theta_0 - \theta}{\sigma/\sqrt{n}}\right)\]
여기서 \(Z \sim N(0,1)\).
유의수준 조건 (\(\theta = \theta_0\) 에서 Type I Error = \(\alpha\)):
\[\beta(\theta_0) = \alpha \implies P(Z > c) = \alpha \implies c = z_\alpha\]
검정력 조건 (\(\theta = \theta_0 + \delta\) 에서 검정력 = \(1 - \beta\)):
\[\beta(\theta_0 + \delta) = 1 - \beta \implies P\!\left(Z > z_\alpha - \frac{\delta}{\sigma/\sqrt{n}}\right) = 1 - \beta\]
\[\implies z_\alpha - \frac{\delta\sqrt{n}}{\sigma} = -z_\beta\]
\[\implies \frac{\delta\sqrt{n}}{\sigma} = z_\alpha + z_\beta\]
\[n = \left\lceil \left(\frac{(z_\alpha + z_\beta)\sigma}{\delta}\right)^2 \right\rceil \tag{1}\]
- \(z_\alpha = \Phi^{-1}(1-\alpha)\): 유의수준에 대응하는 표준 정규 분위수
- \(z_\beta = \Phi^{-1}(1-\beta)\): Type II 오류에 대응하는 분위수
- \(\delta = \theta_1 - \theta_0\): 감지 목표 효과 크기 (양수)
- \(\sigma\): 표준 편차
예: \(\alpha = 0.05\), \(\beta = 0.20\), \(\delta = \sigma\) 이면: \(z_{0.05} = 1.645\), \(z_{0.20} = 0.842\)
\(n = \lceil (1.645 + 0.842)^2 \rceil = \lceil 6.18 \rceil = 7\)
양측 검정 (\(H_0: \theta = \theta_0\) vs \(H_1: \theta \neq \theta_0\)):
\[n = \left\lceil \left(\frac{(z_{\alpha/2} + z_\beta)\sigma}{\delta}\right)^2 \right\rceil \tag{2}\]
유의수준의 \(\alpha\) 를 \(\alpha/2\) 로 교체하는 이유: 양측 기각역이므로 각 꼬리에 \(\alpha/2\).
3 이표본 검정 (Two-Sample)
두 독립 정규 집단 \(X \sim N(\mu_X, \sigma^2)\), \(Y \sim N(\mu_Y, \sigma^2)\) (등분산 가정). 검정: \(H_0: \mu_X = \mu_Y\) vs \(H_1: \mu_X \neq \mu_Y\).
검정 통계량: \(T = (\bar{X} - \bar{Y}) / (s_p \sqrt{1/n_X + 1/n_Y})\)
균형 설계 (\(n_X = n_Y = n\)) 시, 표준 오차 \(= \sigma\sqrt{2/n}\).
\[n = \left\lceil \frac{2(z_{\alpha/2} + z_\beta)^2 \sigma^2}{\delta^2} \right\rceil \tag{3}\]
여기서 \(\delta = |\mu_X - \mu_Y|\).
즉, 단일 표본에서 \(\sigma^2\) 이 \(2\sigma^2\) 으로 바뀐 것 — 두 집단을 비교하므로 분산이 두 배가 된다.
비균형 설계 (\(n_Y = k \cdot n_X\)): \[n_X = \left\lceil \frac{(1 + 1/k)(z_{\alpha/2} + z_\beta)^2 \sigma^2}{\delta^2} \right\rceil\]
모르는 \(\sigma\) 의 경우: \(t\)-분포로 검정하므로 \(z_{\alpha/2}\) 대신 \(t_{\alpha/2, n-1}\) 을 써야 하지만, \(n\) 에 의존하여 반복 계산이 필요하다. 실무에서는 정규 근사로 먼저 구한 후 1~2 단계 반복 수정한다.
4 효과 크기 (Effect Size)
4.1 Cohen’s d (평균 차이)
\[d = \frac{|\mu_1 - \mu_2|}{\sigma} = \frac{\delta}{\sigma}\]
| Cohen의 기준 | 해석 | d 값 |
|---|---|---|
| 소 (small) | 미약한 차이 | 0.2 |
| 중 (medium) | 실질적 차이 | 0.5 |
| 대 (large) | 명확한 차이 | 0.8 |
이표본 양측 검정, \(\alpha = 0.05\), \(1 - \beta = 0.80\) 에서:
| d | 필요 \(n\) (집단당) |
|---|---|
| 0.2 (소) | 197 |
| 0.5 (중) | 32 |
| 0.8 (대) | 13 |
효과 크기가 작을수록 표본이 기하급수적으로 늘어난다는 점을 직관적으로 보여준다.
4.2 Cohen’s f (ANOVA용)
\(G\) 개 집단의 분산 분석에서:
\[f = \frac{\sigma_m}{\sigma_e} = \sqrt{\frac{\sum_{g=1}^{G} (\mu_g - \mu)^2 / G}{\sigma^2}}\]
여기서 \(\sigma_m\) 은 집단 평균의 표준 편차, \(\sigma_e\) 는 오차 표준 편차.
| f 값 | 해석 |
|---|---|
| 0.10 | 소 |
| 0.25 | 중 |
| 0.40 | 대 |
4.3 Cohen’s h (비율 검정용)
두 비율 \(p_1\), \(p_2\) 를 비교할 때 효과 크기:
\[h = 2\arcsin\!\left(\sqrt{p_1}\right) - 2\arcsin\!\left(\sqrt{p_2}\right)\]
아크사인 변환은 이항 비율의 분산을 안정화한다. \(|h|\) 의 해석은 Cohen’s d와 유사하다.
5 ANOVA 표본 크기
\(G\) 개 집단, 집단당 \(n\) 명, 등분산 \(\sigma^2\).
비중심 F-분포(non-central F)를 이용한다. 비중심 모수:
\[\lambda = n \cdot \frac{\sum_{g=1}^{G}(\mu_g - \mu)^2}{\sigma^2} = n \cdot G \cdot f^2\]
\(F_{\alpha, G-1, G(n-1)}\) 의 기각역을 비중심 분포에서 평가하여 검정력 \(1-\beta\) 를 만족하는 최소 \(n\) 을 수치적으로 찾는다.
근사 공식 (균형 설계):
\[n \approx \left\lceil \frac{(z_{\alpha/G} + z_\beta)^2}{f^2} \right\rceil\]
(정확한 계산은 R의 power.anova.test() 또는 Python의 statsmodels.stats.power 사용)
6 비율 검정 (Proportion Test)
단일 비율: \(H_0: p = p_0\) vs \(H_1: p \neq p_0\).
\[n = \left\lceil \frac{\left(z_{\alpha/2}\sqrt{p_0(1-p_0)} + z_\beta\sqrt{p_1(1-p_1)}\right)^2}{(p_1 - p_0)^2} \right\rceil \tag{4}\]
해석: 분자의 두 항은 각각 \(H_0\) 와 \(H_1\) 하에서의 표준 편차이다. \(H_0\) 에서 \(p_0(1-p_0)\), \(H_1\) 에서 \(p_1(1-p_1)\) — 두 분포의 분산이 다르기 때문에 단일 표본 공식보다 복잡하다.
7 검정력 곡선과 표본 크기 시각화
표본 크기가 검정력에 미치는 영향을 시각화하면 설계 결정에 직관적 도움이 된다.
\[\beta_n(\theta_0 + \delta) = 1 - \Phi\!\left(z_{\alpha/2} - \frac{\delta\sqrt{n}}{\sigma}\right) + \Phi\!\left(-z_{\alpha/2} - \frac{\delta\sqrt{n}}{\sigma}\right)\]
\(n\) 이 커질수록 \(\delta\sqrt{n}/\sigma\) 가 커지고, 검정력이 1에 수렴한다.
8 코드 예시
8.1 Step 1: 순수 Python — 표본 크기 직접 계산
import numpy as np
from scipy.stats import norm
import math
def sample_size_one_sample(
delta: float,
sigma: float,
alpha: float = 0.05,
power: float = 0.80,
alternative: str = "two-sided"
) -> int:
"""단일 표본 정규 검정 표본 크기 계산 (알려진 σ)."""
beta = 1 - power
z_beta = norm.ppf(1 - beta)
if alternative == "two-sided":
z_alpha = norm.ppf(1 - alpha / 2)
else:
z_alpha = norm.ppf(1 - alpha)
n = ((z_alpha + z_beta) * sigma / delta) ** 2
return math.ceil(n)
def sample_size_two_sample(
delta: float,
sigma: float,
alpha: float = 0.05,
power: float = 0.80,
ratio: float = 1.0, # n2 = ratio * n1
alternative: str = "two-sided"
) -> tuple:
"""이표본 정규 검정 표본 크기 계산 (등분산, 알려진 σ)."""
beta = 1 - power
z_beta = norm.ppf(1 - beta)
if alternative == "two-sided":
z_alpha = norm.ppf(1 - alpha / 2)
else:
z_alpha = norm.ppf(1 - alpha)
n1 = (1 + 1/ratio) * ((z_alpha + z_beta) * sigma / delta) ** 2
n1 = math.ceil(n1)
n2 = math.ceil(n1 * ratio)
return n1, n2
def sample_size_proportion(
p0: float, p1: float,
alpha: float = 0.05, power: float = 0.80,
alternative: str = "two-sided"
) -> int:
"""단일 비율 검정 표본 크기 (식 4)."""
beta = 1 - power
z_beta = norm.ppf(1 - beta)
z_alpha = norm.ppf(1 - alpha/2) if alternative == "two-sided" else norm.ppf(1 - alpha)
num = (z_alpha * np.sqrt(p0*(1-p0)) + z_beta * np.sqrt(p1*(1-p1))) ** 2
denom = (p1 - p0) ** 2
return math.ceil(num / denom)
# ── 표본 크기 표 출력 ────────────────────────────────────────
from scipy.stats import norm
print("=== 단일 표본 양측 검정 (α=0.05, 1-β=0.80, σ=1) ===")
print(f"{'δ/σ (Cohen d)':15s} | {'n':5s}")
print("-" * 25)
for d in [0.2, 0.3, 0.5, 0.8, 1.0, 1.5, 2.0]:
n = sample_size_one_sample(delta=d, sigma=1.0, alpha=0.05, power=0.80)
print(f"{d:15.1f} | {n:5d}")
print("\n=== 이표본 균형 설계 (α=0.05, 1-β=0.80, σ=1) ===")
print(f"{'δ/σ (Cohen d)':15s} | {'n (각 집단)':10s}")
print("-" * 30)
for d in [0.2, 0.3, 0.5, 0.8, 1.0, 1.5]:
n1, n2 = sample_size_two_sample(delta=d, sigma=1.0, alpha=0.05, power=0.80)
print(f"{d:15.1f} | {n1:10d}")8.2 Step 2: statsmodels 실무 코드
from statsmodels.stats.power import (
TTestPower, TTestIndPower, NormalIndPower, FTestAnovaPower
)
import numpy as np
# 단일 표본 t-검정 (미지 σ — t 분포 사용)
analysis = TTestPower()
# n 계산
n_required = analysis.solve_power(
effect_size=0.5, # Cohen's d
alpha=0.05,
power=0.80,
alternative="two-sided"
)
print(f"단일 표본, d=0.5, 필요 n = {n_required:.1f} → {int(np.ceil(n_required))}")
# 이표본 t-검정
analysis_2 = TTestIndPower()
n_required_2 = analysis_2.solve_power(
effect_size=0.5, alpha=0.05, power=0.80,
ratio=1.0, alternative="two-sided"
)
print(f"이표본, d=0.5, 필요 n (집단당) = {n_required_2:.1f} → {int(np.ceil(n_required_2))}")
# ANOVA
analysis_anova = FTestAnovaPower()
n_required_anova = analysis_anova.solve_power(
effect_size=0.25, # Cohen's f
alpha=0.05, power=0.80, k_groups=3
)
print(f"ANOVA (G=3), f=0.25, 필요 n (집단당) = {n_required_anova:.1f} → {int(np.ceil(n_required_anova))}")8.3 Step 3: 검정력 곡선 시각화
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm
alpha = 0.05
z_alpha2 = norm.ppf(1 - alpha/2)
sigma = 1.0
delta = 0.5 # 감지 목표 효과 크기
sample_sizes = np.arange(5, 201, 1)
effect_sizes = [0.2, 0.5, 0.8]
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
# 왼쪽: 효과 크기별 검정력 곡선
ax1 = axes[0]
for d in effect_sizes:
ncp = d * np.sqrt(sample_sizes) / sigma # 비중심 모수
power = 1 - norm.cdf(z_alpha2 - ncp) + norm.cdf(-z_alpha2 - ncp)
ax1.plot(sample_sizes, power, label=f"d = {d}")
ax1.axhline(0.80, color="red", linestyle="--", label="목표 검정력 0.80")
ax1.set_xlabel("표본 크기 n")
ax1.set_ylabel("검정력 (1 - β)")
ax1.set_title("표본 크기 vs 검정력 (α=0.05, 단일 표본 양측 검정)")
ax1.legend()
ax1.grid(True, alpha=0.3)
# 오른쪽: 표본 크기 결정 테이블 시각화
ax2 = axes[1]
deltas = np.linspace(0.1, 2.0, 100)
powers = [0.70, 0.80, 0.90]
for pw in powers:
z_beta = norm.ppf(pw)
ns = np.ceil(((z_alpha2 + z_beta) / deltas) ** 2)
ax2.plot(deltas, ns, label=f"검정력 {pw:.0%}")
ax2.set_xlabel("효과 크기 δ/σ (Cohen's d)")
ax2.set_ylabel("필요 표본 크기 n")
ax2.set_title("효과 크기 vs 필요 표본 크기 (α=0.05)")
ax2.set_ylim(0, 300)
ax2.axvline(0.2, color="gray", linestyle=":", alpha=0.5, label="소/중/대")
ax2.axvline(0.5, color="gray", linestyle=":", alpha=0.5)
ax2.axvline(0.8, color="gray", linestyle=":", alpha=0.5)
ax2.legend()
ax2.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig("sample_size_power.png", dpi=120)
plt.show()9 실무 지침
9.1 표본 크기 결정의 4단계
임상/과학적으로 의미 있는 최소 효과 크기 \(\delta\) 를 지정한다. “통계적으로 유의”가 아니라 “임상적으로 의미 있는 최소 차이”를 먼저 정의해야 한다.
분산 \(\sigma^2\) 를 선행 연구, 파일럿 연구, 또는 문헌에서 추정한다. \(\sigma\) 불확실 시 보수적으로 큰 값을 사용한다.
\(\alpha\)와 검정력 \(1-\beta\) 를 사전에 지정한다. 규제 임상시험: \(\alpha = 0.025\) (단측) 또는 \(0.05\) (양측), \(1-\beta = 0.80\) or \(0.90\).
탈락률, 불순응률, 다중 검정 보정을 반영한다. 예: 20% 탈락 예상 시 계산된 \(n\) 을 \(n / (1 - 0.20)\) 으로 상향.
9.2 흔한 실수
| 실수 | 결과 | 대안 |
|---|---|---|
| \(\delta\) 를 너무 크게 설정 | \(n\) 과소 → 검정력 부족 | 파일럿 데이터 기반 추정 |
| \(\sigma\) 과소 추정 | \(n\) 과소 | 문헌의 보수적 추정 사용 |
| 단측/양측 혼동 | \(n\) 10~20% 오차 | 사전에 방향성 결정 |
| 다중 1차 평가변수 | 보정 없으면 FWER 팽창 | Bonferroni 또는 Hochberg 반영 |
| 탈락률 미반영 | 실질 \(n\) 부족 | 탈락률 명시적 고려 |
10 관련 주제
선행 지식
후속 주제