용어 설명

  • 사후 검정 (Post-hoc test): ANOVA에서 “적어도 하나의 집단이 다르다”는 결과가 나온 후, 구체적으로 어떤 집단 쌍(pair)이 다른지 찾아내는 추가 분석
  • 다중비교 (Multiple comparisons): 여러 집단을 동시에 쌍별로 비교하는 것. 비교 횟수가 늘어나면 우연히 유의하게 나올 확률이 증가
  • FWER (Family-Wise Error Rate): 여러 번 검정할 때, 한 번이라도 잘못 기각할(Type I Error) 확률. 예: 10번 비교하면 5% 기준으로도 전체 오류 확률이 ~40%로 상승
  • 쌍별 비교 (Pairwise comparison): 집단 A-B, A-C, B-C처럼 두 집단씩 짝지어 평균을 비교하는 것
  • 보수적 검정 (Conservative test): 유의수준 기준을 엄격하게 적용하여 Type I Error를 줄이는 대신, 실제 차이를 놓칠(Type II Error) 위험이 높아지는 검정

ANOVA란?


ANOVA

Summary

  • 3개 이상의 집단(표본)이 동일한 모집단에서 샘플링된 것인지 확인할 수 있는 확률적 가이드라인을 잡아주는 기법
  • t-test는 2개의 집단에서만 본 것과 차별점.
  • F-stat을 결과값으로 하고 해석은 ‘적어도 한 집단은 모집단에서 추출되었을 확률이 낮다.‘로 할 수 있음.
  • 그렇다면 모집단에서 나오지 않은 것으로 추정되는 표본을 찾을 수 있냐? Post-hoc(사후 검정)

용어 설명

  • 더미변수 (Dummy variable): 범주형 변수를 0/1로 코딩한 것. 예: 집단 B = 1, 나머지 = 0. ANOVA 내부에서 회귀처럼 작동할 때 사용
  • 주효과 (Main effect): 각 독립변수가 종속변수에 미치는 독립적인 효과. Two-way ANOVA에서 요인 A의 효과, 요인 B의 효과 각각
  • 교호작용 (Interaction effect): 두 독립변수의 효과가 서로 영향을 미치는 경우. “교수법 효과가 성별에 따라 다르다” 같은 상황
  • 구형성 (Sphericity): 반복측정 ANOVA의 추가 가정. 모든 조건 쌍 간 차이의 분산이 동일해야 함. Mauchly’s test로 검정
  • F 통계량 (F-statistic): 집단 간 분산 / 집단 내 분산. 값이 클수록 집단 간 차이가 오차에 비해 큰 것
  • Cohen’s f: ANOVA용 효과 크기. η²에서 변환: . 0.10(small), 0.25(medium), 0.40(large)

Implementation

import statsmodels.api as sm
from statsmodels.formula.api import ols
from statsmodels.stats.anova import anova_lm
import pandas as pd
 
df = pd.DataFrame({ # Data sample
	'score': [10, 12, 13, 15, 20, 21, 19, 25, 28],
	'group': ['A','A','A','B','B','B','C','C','C']
})
 
# OLS(Ordinary Least Square) model fit.
# C means categorical value
# score: dependent var
# group: independent var
model = ols('score ~ C(group)', data=df).fit() 
 
# generate ANOVA table 
anova_table = sm.stats.anova_lm(model, typ=2) 
print(anova_table)

Relationship between ANOVA and OLS


NOTE

ANOVA는 OLS 의 일종. 아래와 같이 수식적으로 표현 가능.

  • : 전체 평균
  • : 그룹 i의 효과
  • : 오차항

조금 더 자세히 알아보자.

Example

아래와 같은 데이터 셋이 있다 가정하자.

idxfeature1y
1A5
2A7
3B9
4B11
5C13
6C15

Recap: ANOVA는 기본적으로 categorical independent var를 위한 regression!

ANOVA는 matrix form으로 다음과 같이 써질 수 있는데,

관례 상 회귀 시 한 group을 baseline으로 잡고, 나머지 그룹 간 차를 변수로 두는 경우가 많은데 여기선 A를 baseline으로 set.

그렇다면, Dummy는 이렇게 잡을 수 있음.

그렇다면, 이제 데이터와 기울기는

물론 위의 는 baseline 대비 임.

model이 fitting하는 건, 위 식을 통해 예측한 각 y 값과 ground_truth 간 RSS 혹은 LS를 minimizing 함.

ANOVA의 유형


One-way ANOVA

  • 독립변수(요인) 1개, 수준(집단) 3개 이상
  • 예: 3가지 교수법 → 시험 점수 비교

Two-way ANOVA (Factorial ANOVA)

  • 독립변수 2개, 주효과(main effect) + 교호작용(interaction) 검정
  • 예: 교수법(3) × 성별(2) → 시험 점수

수식 변수 풀이

  • : 요인 A의 수준 i, 요인 B의 수준 j, 관측 k의 종속변수 값
  • : 전체 평균
  • : 요인 A(예: 교수법)의 수준 i의 주효과
  • : 요인 B(예: 성별)의 수준 j의 주효과
  • : A와 B의 교호작용 효과 — 두 요인의 조합에 따른 추가 효과
  • : 오차항 — 모형으로 설명되지 않는 개인 차이
Sourcedf
Factor Aa - 1
Factor Bb - 1
A × B(a-1)(b-1)
ErrorN - ab

Repeated-Measures ANOVA (RM-ANOVA)

  • 같은 피험자가 모든 조건에 참여 (within-subject design)
  • 개인 간 변동을 분리하여 오차 감소 → 검정력 향상
  • 추가 가정: 구형성(sphericity) — Mauchly’s test로 검정

수식 변수 풀이

  • : 조건 i의 효과 (관심 대상)
  • : 피험자 j의 개인 효과 — 각 피험자의 전반적 수준 차이를 분리하여 오차 감소
  • 직관: 피험자 효과를 분리하면 이 줄어들어 → F값 증가 → 검정력 향상
  • : 피험자 j의 효과 (subject effect)

구형성 위반 시

  • Greenhouse-Geisser 보정 (ε < 0.75일 때)
  • Huynh-Feldt 보정 (ε ≥ 0.75일 때)
  • 또는 LMM 사용 (구형성 가정 불필요)

Mixed ANOVA

  • Between-subject factor + Within-subject factor 동시 포함
  • 예: 집단(실험/통제) × 시점(사전/사후/추후)

가정 (Assumptions)

가정검정 방법위반 시 대안
정규성Shapiro-Wilk, Q-Q plotKruskal-Wallis test
등분산성Levene’s testWelch’s ANOVA, Games-Howell post-hoc
독립성연구 설계LMM
구형성 (RM만)Mauchly’s testG-G / H-F 보정, LMM

Effect Size

Eta-squared 참조

지표수식해석 (S/M/L)
η².01 / .06 / .14
partial η².01 / .06 / .14
ω²편향 보정
Cohen’s f.10 / .25 / .40

사후 검정 (Post-hoc)

ANOVA가 유의하면 → “어떤 집단 쌍이 다른가?” → Post-hoc(사후 검정)

방법등분산 가정보수성권장 상황
Tukey HSDYes중간모든 쌍 비교 (가장 일반적)
BonferroniYes높음특정 소수 쌍만 비교
ScheffeYes매우 높음복잡한 대비(contrast)
Games-HowellNo중간등분산 위반 시
DunnettYes중간통제 집단 vs 나머지

확장 구현

Implementation — Two-way & RM-ANOVA

import pingouin as pg
import statsmodels.api as sm
from statsmodels.formula.api import ols
 
# === Two-way ANOVA ===
model = ols('score ~ C(method) * C(gender)', data=df).fit()
anova_table = sm.stats.anova_lm(model, typ=2)
print(anova_table)
 
# === RM-ANOVA (pingouin) ===
rm = pg.rm_anova(data=df, dv='score', within='condition',
                 subject='subject', correction=True)
print(rm[['Source', 'F', 'p-unc', 'p-GG-corr', 'np2', 'eps']])
# p-GG-corr = Greenhouse-Geisser 보정 p-value
# eps = sphericity epsilon
 
# === Mixed ANOVA ===
mixed = pg.mixed_anova(data=df, dv='score',
                       within='time', between='group',
                       subject='subject')
print(mixed)
 
# === Post-hoc (Tukey) ===
posthoc = pg.pairwise_tukey(data=df, dv='score', between='method')
print(posthoc[['A', 'B', 'diff', 'p-tukey', 'hedges']])

관련 문서

원본 링크

Post-hoc 이란?


  • ANOVA가 말해주는 건 ‘적어도 한 쌍에대해 통계적으로 모집단이 유의미하게 다르다.‘인데, 궁금한 건 ‘그래서 어떠한 쌍이 다른 건데?‘일 떄 답을 줌.
  • 방법이 여러 개 있는데 아래 표를 참고.

  • 붉은 표시: 자주 사용되는 method.

Post-hoc method 별 특징