통계적 유의성을 넘어서: 효과 크기 이해하기
효과 크기는 표본 크기와 독립적으로 차이나 관계의 크기를 측정합니다. p-값이 효과가 통계적으로 유의한지를 알려주는 반면, 효과 크기는 그 효과가 실질적으로 얼마나 의미 있는지를 알려줍니다. 이 구분은 연구, 의학, 교육, 비즈니스에서 근거 기반 의사결정에 매우 중요합니다.
신약이 위약 대비 통계적으로 유의한 개선(p < 0.001)을 보이는 제약 임상시험을 생각해 보세요. 효과 크기 없이는 그 개선이 0.1%인지 50%인지 알 수 없습니다. 효과 크기는 이 핵심적인 맥락을 제공하여 이해관계자들이 비용, 부작용, 구현 노력 대비 효과가 가치 있는지 판단하도록 돕습니다.
두 집단을 비교하는 데 가장 흔히 사용되는 효과 크기 측도는 Cohen의 d로, 평균의 차이를 표준편차 단위로 표현합니다. 이 표준화를 통해 서로 다른 연구와 측정 척도 간의 비교가 가능합니다.
효과 크기가 중요한 이유
통계적 유의성은 표본 크기의 영향을 크게 받습니다. 표본이 충분히 크면 사소한 차이도 “유의”하게 나오고, 반대로 중요한 효과도 작은 표본에서는 유의하지 않을 수 있습니다. 효과 크기는 표본 크기에 독립적인 측도를 제공하여 이 문제를 해결합니다.
유의성의 함정
효과 크기를 사용하는 핵심 이유:
- 메타분석: 여러 연구의 효과 크기를 결합하여 전체 효과를 추정 가능
- 검정력 분석: 향후 연구에 필요한 표본 크기 계산에 필수
- 실무적 결정: 개입 시행의 가치가 있는지 판단에 도움
- 재현성: 재현 연구가 목표로 삼을 기준점 제공
Cohen의 d: 표준 효과 크기 측도
Cohen의 d는 두 집단 평균의 차이를 합동 표준편차 단위로 표현합니다:
Cohen의 d
여기서 M₁과 M₂는 집단 평균이고, sp는 다음과 같이 계산되는 합동 표준편차입니다:
합동 표준편차
d의 부호는 방향을 나타냅니다: M₁ > M₂이면 양수, M₁ < M₂이면 음수입니다. 방향이 문맥상 명확할 때는 절대값 |d|를 보고하기도 합니다.
왜 표준편차를 합동할까?
대안적 효과 크기 측도
Cohen의 d가 가장 일반적이지만, 특정 상황에 맞는 대안이 있습니다:
Hedges의 g: 편향 보정 효과 크기
Cohen의 d는 작은 표본에서 모집단 효과 크기를 약간 과대추정합니다. Hedges의 g는 보정 계수를 적용합니다:
Hedges의 g 보정
집단당 표본이 20개 이상이면 차이는 무시할 수 있습니다. 작은 표본(n < 20)에서는 Hedges의 g가 선호됩니다.
Glass의 Δ: 분산이 다른 경우
변동성이 알려진 통제 집단이 있을 때, 통제 집단의 표준편차만 분모로 사용합니다:
Glass의 델타
처치가 분산에 영향을 줄 수 있는 경우(예: 저성과자에게 더 많이 도움이 되는 개입)에 유용합니다.
효과 크기 해석: Cohen의 기준
Jacob Cohen은 d 값 해석을 위한 다음의 관례를 제안했습니다:
| 효과 크기 (d) | 해석 | 집단 간 중첩 |
|---|---|---|
| 0.2 | 소 | 85% 중첩 |
| 0.5 | 중 | 67% 중첩 |
| 0.8 | 대 | 53% 중첩 |
| 1.2 | 매우 큼 | 40% 중첩 |
| 2.0 | 거대 | 19% 중첩 |
맥락이 중요합니다
계산 예시: 교육 개입
한 학교에서 새로운 독서 프로그램을 시험합니다. 통제 집단(n=25): 평균=72, SD=12. 처치 집단(n=30): 평균=79, SD=14. Cohen의 d를 계산합니다:
합동 분산 계산
합동 SD 계산
Cohen의 d 계산
해석
이는 처치 집단에서 무작위로 한 학생을, 통제 집단에서 무작위로 한 학생을 뽑으면 처치 학생이 약 64%의 확률로 더 높은 점수를 받는다는 뜻입니다(중첩에서 계산).
Python 구현
신뢰구간과 함께 효과 크기를 프로그래밍적으로 계산합니다:
import numpy as np
from scipy import stats
def cohens_d(group1, group2):
"""Calculate Cohen's d for two independent groups."""
n1, n2 = len(group1), len(group2)
var1, var2 = np.var(group1, ddof=1), np.var(group2, ddof=1)
# Pooled standard deviation
pooled_std = np.sqrt(((n1-1)*var1 + (n2-1)*var2) / (n1+n2-2))
# Cohen's d
d = (np.mean(group1) - np.mean(group2)) / pooled_std
return d
def hedges_g(group1, group2):
"""Calculate Hedges' g (bias-corrected effect size)."""
n1, n2 = len(group1), len(group2)
d = cohens_d(group1, group2)
# Correction factor for small sample bias
correction = 1 - 3 / (4*(n1+n2) - 9)
return d * correction
# Example usage
control = [68, 72, 75, 70, 69, 74, 71, 73, 76, 72]
treatment = [75, 79, 82, 78, 80, 77, 81, 76, 83, 79]
d = cohens_d(treatment, control)
g = hedges_g(treatment, control)
print(f"Cohen's d: {d:.3f}")
print(f"Hedges' g: {g:.3f}")