본문으로 이동
메뉴 여닫기
환경 설정 메뉴 여닫기
개인 메뉴 여닫기
로그인하지 않음
지금 편집한다면 당신의 IP 주소가 공개될 수 있습니다.
Post-hoc Test; 다중 비교, Multiple Comparison
분산분석에서 집단 평균이 모두 같다는 귀무가설이 기각된 뒤, 어느 집단 사이에 차이가 있는지를 찾는 검정

일원 분산분석의 F 검정은 "적어도 한 집단의 평균이 다르다"는 것만 알려 준다. 어느 집단과 어느 집단이 다른지는 사후 검정으로 확인한다. 이때 집단 쌍마다 t-검정을 따로 반복하면 전체 제1종 오류 확률이 커지므로, 이를 통제하는 다중 비교 방법을 쓴다.

다중 비교 문제

편집 원본 편집

유의수준 α인 독립적인 검정을 m번 하면, 적어도 한 번 잘못 기각할 확률인 가족별 오류율(FWER, family-wise error rate)은 다음과 같다.

FWER=1−(1−α)m

  • α = 0.05일 때 세 집단의 쌍별 비교(m = 3)는 FWER이 약 0.143, 다섯 집단(m = 10)은 약 0.401이 된다.
  • 사후 검정은 비교 전체에 대해 FWER을 α 이하로 묶어 두는 방법이다. 대신 개별 비교의 검정력은 낮아진다.
  • 분산분석 F 검정이 유의하지 않으면 보통 사후 검정을 하지 않는다. F 검정은 더 조사할 가치가 있는지를 알려 주는 예비 검정 역할을 한다.

Tukey HSD(Honestly Significant Difference)는 모든 쌍의 평균 차이를 동시에 비교한다. 스튜던트화 범위 분포 q를 쓰며, 표본 크기가 같으면 신뢰계수가 정확히 1 − α이고 다르면 보수적이 된다(Tukey-Kramer 방식).

y¯i−y¯j±qα;k,N−k2σ^1ni+1nj

Bonferroni 방법은 m개 비교 각각을 α/m 수준에서 검정한다(또는 p-값에 m을 곱한다). 계산이 단순하고 어떤 검정에도 붙일 수 있지만, 비교 수가 많으면 지나치게 보수적이다.

Scheffé 방법은 쌍별 차이뿐 아니라 (μ1 + μ2)/2 − μ3 같은 가능한 모든 대비(contrast)를 동시에 다룬다. 임계값은 (k−1)Fα;k−1,N−k를 쓴다. 쌍별 비교만 할 때는 Tukey보다 신뢰구간이 넓다.

Dunnett 방법은 여러 처리 집단을 하나의 대조군(control)과만 비교한다. 비교 수가 k − 1개로 줄어 모든 쌍을 비교하는 방법보다 검정력이 높다.

Duncan의 다중범위 검정(DMRT)은 평균을 크기순으로 놓고 범위에 따라 다른 임계값을 쓰는 방법으로, 국내 교재와 농학 분야에서 자주 언급된다. FWER을 엄격히 통제하지 않아 차이를 쉽게 찾는 편이다.

방법 비교 대상 언제 쓰나 보수성
Tukey HSD 모든 쌍 모든 쌍별 비교가 관심일 때. 표본 크기가 같으면 가장 알맞다 중간
Bonferroni 미리 정한 m개 비교 계획된 비교 수가 적을 때(대략 집단 수 정도) 비교 수가 많으면 매우 보수적
Scheffé 모든 대비 쌍별 외에 집단 묶음 비교 등 여러 대비를 사후에 탐색할 때 쌍별 비교에서는 가장 보수적
Dunnett 각 처리 대 대조군 신약·신공정을 기존 대조군과 비교할 때 대조군 비교에 특화되어 검정력이 높다
Duncan 모든 쌍 전통적으로 농학 실험 등에서 사용 덜 보수적(차이를 쉽게 찾음)
Games-Howell 모든 쌍 등분산 검정에서 이분산으로 판정됐을 때 등분산 가정 없음
  • 어느 한 방법이 언제나 가장 좋은 것은 아니다. 모든 쌍별 비교면 Tukey, 소수의 계획된 비교면 Bonferroni, 많은 대비면 Scheffé가 유리하다.
fit <- aov(y ~ group, data = df)
summary(fit)
TukeyHSD(fit)                                             # Tukey HSD
pairwise.t.test(df$y, df$group, p.adjust.method = "bonferroni")
library(DescTools)
ScheffeTest(fit)                                          # Scheffé
DunnettTest(y ~ group, data = df, control = "control")    # Dunnett
library(agricolae)
duncan.test(fit, "group", console = TRUE)                 # Duncan
import numpy as np
import pandas as pd
from itertools import combinations
from scipy import stats
from statsmodels.stats.multicomp import pairwise_tukeyhsd
from statsmodels.stats.multitest import multipletests

# 비료 종류별 수확량 (가상의 자료, 집단별 6개)
df = pd.DataFrame({
    "group": ["control"] * 6 + ["A"] * 6 + ["B"] * 6,
    "y": [20, 22, 19, 21, 23, 20,
          24, 26, 25, 23, 27, 25,
          21, 23, 22, 20, 24, 22],
})
groups = {g: d["y"].to_numpy() for g, d in df.groupby("group")}

F, p = stats.f_oneway(*groups.values())
print(f"ANOVA: F={F:.4f}, p={p:.4f}")

# 1) Tukey HSD
print(pairwise_tukeyhsd(endog=df["y"], groups=df["group"], alpha=0.05))

# 2) Bonferroni: 쌍별 t-검정 p-값을 보정
pairs = list(combinations(sorted(groups), 2))
raw = [stats.ttest_ind(groups[a], groups[b]).pvalue for a, b in pairs]
reject, p_adj, _, _ = multipletests(raw, alpha=0.05, method="bonferroni")
for (a, b), p, q, r in zip(pairs, raw, p_adj, reject):
    print(f"{a} vs {b}: p={p:.4f}, Bonferroni p={q:.4f}, reject={r}")

# 3) Dunnett: 대조군(control)과만 비교
res = stats.dunnett(groups["A"], groups["B"], control=groups["control"])
print("Dunnett p (A, B vs control):", np.round(res.pvalue, 4))

실행 결과:

ANOVA: F=13.4865, p=0.0004
 Multiple Comparison of Means - Tukey HSD, FWER=0.05
=====================================================
group1  group2 meandiff p-adj   lower   upper  reject
-----------------------------------------------------
     A       B     -3.0 0.0066 -5.1501 -0.8499   True
     A control  -4.1667 0.0004 -6.3167 -2.0166   True
     B control  -1.1667 0.3612 -3.3167  0.9834  False
-----------------------------------------------------
A vs B: p=0.0043, Bonferroni p=0.0129, reject=True
A vs control: p=0.0005, Bonferroni p=0.0016, reject=True
B vs control: p=0.1918, Bonferroni p=0.5753, reject=False
Dunnett p (A, B vs control): [0.0003 0.2975]
  • 분산분석 p-값이 0.0004로 유의하므로 사후 검정으로 넘어간다.
  • Tukey HSD에서 meandiff는 group2 평균에서 group1 평균을 뺀 값이다. A는 B와 control보다 평균이 높고(신뢰구간이 0을 포함하지 않음, reject=True), B와 control의 차이는 유의하지 않다(신뢰구간이 0을 포함).
  • Bonferroni는 원래 p-값에 비교 수 3을 곱한 값이다. 결론은 Tukey와 같다.
  • Dunnett은 대조군과의 비교 두 개만 하므로 A 대 control의 p-값이 Tukey보다 작다. 처리 A만 대조군과 유의하게 다르다.
  • 쌍별 t-검정을 반복하면 FWER이 1 − (1 − α)m으로 커진다는 점과, 사후 검정이 이를 통제한다는 점을 설명할 수 있어야 한다.
  • 모든 쌍 비교는 Tukey, 대조군과의 비교는 Dunnett, 모든 대비는 Scheffé, 소수의 계획된 비교는 Bonferroni라는 대응을 기억한다.
  • 실기에서는 분산분석 → 사후 검정 결과표에서 어떤 집단 쌍이 다른지(p-adj, 신뢰구간의 0 포함 여부)를 읽어 서술하는 문제가 나올 수 있다.