비모수 통계 검정 선택과 해석: 순위·분포 기반 분석
Mann-Whitney U, Wilcoxon, Kruskal-Wallis, Kolmogorov-Smirnov 검정의 선택 기준, 가정, 효과크기와 해석 방법을 정리한다.
2026-08-14 · 최초 발행 2025-10-14
순위와 경험분포로 가정을 줄이는 검정
정규성이나 등분산성 가정이 흔들리는 데이터에서는 평균 기반 검정만으로 판단하기 어렵다. 비모수 통계는 분포 형태에 강한 가정을 두지 않고, 순위 또는 경험분포를 사용해 가설을 검정한다.
연속형 데이터와 서열형 데이터 모두에 적용할 수 있으며, 이상치·비대칭 분포·작은 표본이 있는 상황에서도 활용된다. 다만 “중앙값 차이”라는 해석은 집단의 분포 형태가 유사할 때에만 적절하다. 검정 결과에는 rank-biserial r, Cliff’s δ, ε²/η², D 같은 효과크기를 함께 제시해 실질적 차이를 드러내는 편이 낫다.
선택 기준은 비교하려는 구조에 달려 있다. 두 독립 집단의 위치를 비교하는지, 같은 대상의 전후 변화를 보는지, 여러 집단을 비교하는지, 분포 자체가 같은지에 따라 검정이 달라진다.
비교 구조에 맞춰 검정을 고른다
Mann-Whitney U로 독립 집단을 비교할 때
Mann-Whitney U는 두 독립 표본의 위치, 즉 분포의 중앙 경향 차이를 검정한다. 관측값이 순서대로 비교될 수 있어야 하며, 위치 차이로 해석하려면 두 집단의 분포 형태가 유사해야 한다. 타이가 있으면 보정이 필요하다.
모든 쌍의 승패를 순위합으로 요약해 U 통계량을 구한다. 효과크기는 rank-biserial r = 1 − 2U/(n1·n2) 또는 Cliff’s δ로 표현할 수 있다. 표본 수가 크게 불균형하거나 분포 폭이 서로 다르면 결과를 단순한 위치 차이로 읽기 어려울 수 있다.
Wilcoxon signed-rank가 맞는 대응 자료
같은 집단의 전후 변화나 짝지어진 두 조건을 비교할 때는 Wilcoxon signed-rank를 사용한다. 차이분포의 대칭성을 가정하며, 0인 차이를 제외한 뒤 순위의 부호 합인 W를 계산한다.
각 차이의 절대값에 순위를 매기고 그 부호를 합산하는 방식이다. r = Z/√N 또는 matched rank-biserial을 효과크기로 보고할 수 있다. 대칭성 가정이 맞지 않는다면 부호검정(Sign test)을 대안으로 검토한다.
Kruskal-Wallis로 여러 독립 집단을 다룰 때
Kruskal-Wallis H는 3개 이상 독립 집단의 위치 차이를 검정한다. 관측값의 순서 비교가 가능해야 하고, 집단별 분포 형태가 유사하다는 가정이 해석의 기반이 된다.
전체 데이터를 순위로 바꾼 뒤 집단별 순위합에서 H 통계량을 계산한다. 유의한 결과가 나왔다면 Dunn 사후분석과 Bonferroni 또는 Holm 다중비교 보정을 이어서 수행한다. 이 검정은 위치 차이뿐 아니라 분포 폭의 차이에도 민감하므로 박스플롯이나 ECDF를 함께 확인해야 한다.
Kolmogorov-Smirnov는 분포 전체를 본다
Kolmogorov-Smirnov(K-S) 검정은 두 표본의 분포가 같은지 확인하거나, 한 표본이 특정 이론분포에 적합한지 평가한다. 경험누적분포(ECDF) 사이의 최대 거리 D를 이용하므로 위치뿐 아니라 분포 형태 전반의 차이에 민감하다.
연속분포를 전제로 하며, 이산 데이터나 타이가 많은 데이터에서는 성능이 떨어질 수 있다. 모수 추정이 포함된 경우에는 Lilliefors 보정이 필요하다. Anderson-Darling, Cramér–von Mises도 대안이 될 수 있다.
검정 전후에 확인할 항목
독립성, 대칭성, 분포 형태의 유사성은 비모수 검정에서도 확인해야 할 최소 가정이다. 분석 전에 EDA로 왜도, 타이, 이상치 여부를 점검하고 분석 단위와 대응 구조를 먼저 확정한다. 표본수가 작으면 exact p를, 충분히 크면 정규근사를 사용한다.
결과에는 U, W, H, D 통계량과 p값을 기록하고, r, δ, ε²/η² 같은 효과크기를 함께 제시한다. 부트스트랩 신뢰구간을 병행하면 해석력을 높일 수 있다.
Kruskal-Wallis 이후의 사후분석에는 Dunn 또는 Conover 검정을 사용할 수 있다. 보정 방법으로는 Holm이 균형 잡힌 선택지가 될 수 있고, 실무에서는 Benjamini-Hochberg(FDR)도 권장된다. 순위 계산에서는 타이에 평균순위를 부여하고 분산 보정을 적용한다. Wilcoxon에서는 0 차이를 제외하며, K-S는 타이가 많을수록 다른 검정을 검토해야 한다.
분석 흐름에서 분기되는 지점
검정별 선택과 운영 특성
| 검정 | 성능(계산/효율) | 확장성(집단 수/표본) | 일관성(가정 위반 민감도) | 안정성(이상치/타이) | 운영 편의(해석/도구) |
|---|---|---|---|---|---|
| Mann-Whitney U | 높음, O(n log n) 순위연산 | 2집단 전용, 큰 표본도 안정 | 분포형태 차이에 민감 | 이상치 강건, 타이 보정 필요 | 해석 용이, 도구 광범위 |
| Wilcoxon signed-rank | 높음, 짝 데이터 효율적 | 한 쌍 비교 전용 | 대칭성 위반 시 민감 | 0 차이 제거, 이상치 영향 완화 | 해석 용이, 광범위 지원 |
| Kruskal-Wallis | 높음, 다집단 확장 | 다집단 가능, 불균형 허용 | 형태 이질 시 해석 주의 | 이상치 강건, 타이 보정 | 사후검정 필요, 지원 풍부 |
| Kolmogorov-Smirnov | 높음, ECDF 기반 | 1/2표본 모두 가능 | 이산·타이에 민감 | 연속 가정 위반 시 불안정 | 분포 전반 비교에 유용 |
데이터 특성에 따른 활용 장면
의료 임상 A/B 비교에서는 약물군과 위약군의 생체지표에 Mann-Whitney U를 적용할 수 있다. 동일 환자의 전후 변화는 Wilcoxon으로 분석하고 r 효과크기를 함께 보고한다.
제조 공정에서 3개 이상 생산라인의 불량 지표를 비교할 때는 Kruskal-Wallis와 Dunn 사후분석을 연결한다. 라인 간 분포 폭 차이도 함께 점검해야 해석을 보완할 수 있다.
디지털 제품의 A/B/n 실험에서 클릭시간이나 체류시간처럼 비정규 척도를 다룰 때는 Mann-Whitney U 또는 Kruskal-Wallis가 맞는다. 다중비교 보정과 Cliff’s δ를 함께 사용하면 비즈니스 의미를 전달하기 좋다.
금융 리스크 모델에서는 예측확률 분포와 이론분포의 적합도를 1표본 K-S로 점검할 수 있다. 이산값 또는 타이가 많다면 Anderson-Darling이나 Epps-Singleton을 검토한다.
Python으로 검정과 사후분석 실행하기
Python 3.10+, numpy 1.24+, scipy 1.11+, scikit-posthocs 0.7+ 환경을 전제로 한다. 사후분석까지 실행하려면 pip install numpy scipy scikit-posthocs가 필요하다.
import numpy as np
from scipy import stats
import scikit_posthocs as sp
rng = np.random.default_rng(42)
# 샘플 데이터 생성
a = rng.normal(0, 1, 40)
b = rng.normal(0.4, 1.2, 50) # 분포형태 다소 상이
pre = rng.normal(10, 3, 30)
post = pre + rng.normal(0.8, 2, 30) # 전후 변화
# Mann-Whitney U (독립 2표본)
u_stat, p_u = stats.mannwhitneyu(a, b, alternative='two-sided', method='asymptotic')
n1, n2 = len(a), len(b)
r_rb = 1 - (2*u_stat)/(n1*n2) # rank-biserial correlation
print(f"Mann-Whitney U={u_stat:.1f}, p={p_u:.4f}, rank-biserial r={r_rb:.3f}")
# Wilcoxon signed-rank (대응)
w_stat, p_w = stats.wilcoxon(post, pre, zero_method='wilcox', alternative='two-sided', method='auto')
# 효과크기 r = Z/sqrt(N): SciPy는 Z를 직접 반환하지 않으므로 근사 Z 계산
# 정규근사 기반 Z 추정 (소표본 exact 사용 시 생략 가능)
# 주의: ties/zero 보정 포함 정확 Z는 별도 구현 필요
z_w = stats.norm.isf(p_w/2) * (1 if np.median(post-pre) > 0 else -1)
r_w = z_w / np.sqrt(len(pre))
print(f"Wilcoxon W={w_stat:.1f}, p={p_w:.4f}, r≈{r_w:.3f}")
# Kruskal-Wallis (3집단)
c = rng.normal(-0.2, 0.9, 35)
h_stat, p_h = stats.kruskal(a, b, c)
print(f"Kruskal-Wallis H={h_stat:.2f}, p={p_h:.4f}")
if p_h < 0.05:
# Dunn 사후분석 + Holm 보정
data = np.concatenate([a, b, c])
groups = (['A']*len(a)) + (['B']*len(b)) + (['C']*len(c))
dunn = sp.posthoc_dunn([data[ np.array(groups)==g ] for g in ['A','B','C']], p_adjust='holm')
print("Dunn 사후분석 p-값(행/열 = A,B,C):\n", dunn)
# Kolmogorov-Smirnov (2표본)
d_stat, p_d = stats.ks_2samp(a, b, alternative='two-sided', method='auto')
print(f"KS 2-sample D={d_stat:.3f}, p={p_d:.4f}")
# Kolmogorov-Smirnov (1표본 적합도, N(0,1) 가정)
d1_stat, p1_d = stats.kstest(a, 'norm', args=(0,1), alternative='two-sided', method='auto')
print(f"KS 1-sample D={d1_stat:.3f}, p={p1_d:.4f}")
소표본이거나 타이가 많은 경우에는 method='exact' 또는 'auto'를 사용하고 결과를 신중히 해석한다. Wilcoxon의 Z 기반 r은 근사치이므로, 보고할 때 W·p·방향성과 부트스트랩 CI를 병행하는 편이 좋다.
가정 위반 데이터에서 얻는 분석상 이점
정규성 위반 상황에서 1종 오류 제어의 안정성을 높이고 위치 기반 비교의 검정력을 확보할 수 있다. 정상분포에서도 효율 손실은 제한적이며, Mann-Whitney는 t-검정 대비 효율 ~0.95 수준로 알려짐.
이상치·왜도·타이에 강건한 분석 체계를 마련할 수 있고, 사전 가정 검증 부담도 줄어든다. 전처리, 가정 점검, 검정 선택, 보정, 해석을 일관된 절차로 관리하면 재현 가능하고 신뢰도 있는 분석 보고서를 만들 수 있다.