본문으로 바로가기

Kruskal-Wallis 검정: 정규성 없이 여러 집단 비교하기

Kruskal-Wallis 검정에 대한 실용 가이드 — 개념, 작동 원리, ANOVA 대비 사용 시점, Python과 R에서의 실행 및 해석 방법.
업데이트됨 2026년 5월 4일  · 9분 읽다

AI로 탐색하기

ChatGPT에서 열기Claude에서 열기Perplexity에서 열기

데이터가 정규분포를 따르면 여러 집단 비교는 쉽습니다. 문제는 대부분의 실제 데이터가 그렇지 않다는 점입니다.

ANOVA를 기본 검정으로 사용하면, 데이터가 정규분포를 따른다고 가정하기 때문에 잘못된 결론에 도달할 수 있습니다. 치우친 분포나 작은 표본처럼 정규성이 깨지면 다른 접근이 필요합니다.

Kruskal-Wallis 검정이 바로 그 대안입니다. 이는 ANOVA의 비모수적 대안으로, 원시값 대신 순위에 기반해 작동하므로 정규분포를 가정하지 않습니다.

이 글에서는 개념과 수식, Python과 R에서 실행하는 방법, 그리고 결과를 해석하는 법을 다룹니다.

Kruskal-Wallis 검정이란?

Kruskal-Wallis 검정은 세 개 이상의 독립 집단을 비교하는 비모수 방법입니다. 모든 관측치를 순위로 변환하고, 원시값 대신 집단 간 순위를 비교합니다.

이를 Mann-Whitney U 검정의 확장판으로 볼 수 있습니다. 이에 대해서도 제가 글을 쓴 바 있습니다.

Mann-Whitney U는 동일한 순위 기반 비교이지만 두 집단에만 적용됩니다. Kruskal-Wallis는 이를 세 집단 이상으로 확장합니다. 여러 집단이 있고 ANOVA를 쓸 수 없다면 이 검정을 사용하면 됩니다.

원시값이 아니라 순위를 사용하므로, 데이터가 특정 분포를 따른다고 가정하지 않습니다. 실제 데이터는 한 가지 분포에 완벽히 맞지 않는 경우가 많기에 유용합니다.

Kruskal-Wallis 검정을 사용할 때

다음과 같은 상황에서 Kruskal-Wallis 검정이 잘 맞습니다:

  • 세 개 이상의 독립 집단을 비교하려는 경우
  • 서열형 또는 연속형 데이터(예: 리커트 척도 평점, 측정값)
  • 비정규 분포(왜도, 이상치, 소표본 등 ANOVA가 다루기 어려운 경우)
  • 작은 표본 크기로 정규성을 확인하기 어려운 경우

간단한 예를 보겠습니다.

세 개 반의 시험 점수를 비교한다고 가정해 보세요. 점수 분포는 치우쳐 있고 표본도 작아 ANOVA는 적합하지 않습니다. Kruskal-Wallis는 정규성을 요구하지 않으므로 사용할 수 있습니다. 최소한 한 반의 점수가 다른 반들과 달랐는지, 데이터가 뒷받침하지 않는 가정을 두지 않고 알려줍니다.

Kruskal-Wallis 검정 vs. ANOVA

두 검정 모두 집단을 비교하지만 방식이 다릅니다.

ANOVA는 집단의 평균을 비교하며, 데이터가 정규분포를 따르고 분산이 대략 유사하다고 가정합니다. 가정이 충족되면 더 나은 선택입니다. 통계적 검정력이 더 높고 해석도 쉽습니다.

Kruskal-Wallis는 집단의 분포를 순위를 이용해 비교합니다. 정규성이나 등분산을 신경 쓰지 않습니다. 더 유연하지만, 그만큼 통계적 검정력은 다소 떨어집니다.

간단 비교 표는 다음과 같습니다:

ANOVA compared to Kruskal-Wallis test

ANOVA와 Kruskal-Wallis 검정 비교

데이터가 정규분포를 따른다면 ANOVA를 사용하세요. 그렇지 않거나 확인할 수 없다면 Kruskal-Wallis를 사용하세요.

Kruskal-Wallis 검정 수식

Kruskal-Wallis 검정은 H라는 하나의 검정통계량으로 요약됩니다. 수식은 다음과 같습니다:

Kruskal-Wallis formula

Kruskal-Wallis 수식

구성요소는 다음과 같습니다:

  • N - 모든 집단의 관측치 총합

  • k - 집단의 수

  • n_i - 집단 i의 관측치 수

  • R_i - 집단 i에 할당된 순위의 합

이 수식은, 모든 집단이 동일하다면 기대되는 수준에서 각 집단의 순위 합이 얼마나 벗어나는지를 측정합니다. H가 크면 집단 간 차이가 크고, H가 작으면 차이가 크지 않다는 뜻입니다.

H를 계산한 뒤에는 자유도 k - 1인 카이제곱 분포와 비교해 p-값을 구합니다.

Kruskal-Wallis 검정의 작동 방식

Kruskal-Wallis 검정은 네 단계로 수행합니다:

  1. 모든 집단을 합칩니다: 모든 집단의 관측치를 하나의 데이터셋으로 합칩니다
  2. 모든 관측치에 순위를 매깁니다: 합친 데이터를 작은 값부터 큰 값까지 정렬하고 순위를 부여합니다. 가장 작은 값은 1, 다음은 2, 이런 식입니다. 값이 같으면 해당 순위들의 평균을 공유합니다.
  3. 순위 합을 계산합니다: 순위를 원래 집단별로 다시 나눕니다. 각 집단의 순위를 모두 더합니다. 이것이 수식의 R_i입니다
  4. 검정통계량을 계산합니다: 순위 합을 H 수식에 대입합니다. 집단이 비슷하면 순위 합이 서로 가깝고 H는 작습니다. 한 집단이 일관되게 더 높은(혹은 낮은) 순위를 받으면 H가 커집니다

이게 전부입니다!

보시다시피 이 검정은 실제 값 자체보다, 전체 속에서 값이 어느 위치에 있는지만을 봅니다.

Python에서의 Kruskal-Wallis 검정

Python의 scipy 라이브러리는 Kruskal-Wallis 검정을 위한 내장 함수를 제공합니다. 수식을 직접 구현할 필요가 없습니다. 예제를 살펴보겠습니다.

세 반의 시험 점수를 비교한다고 가정합니다. 검정은 다음과 같이 수행합니다:

from scipy import stats

# Exam scores
class_a = [78, 85, 90, 72, 88]
class_b = [65, 70, 68, 74, 60]
class_c = [88, 92, 95, 85, 91]

# Run the test
statistic, p_value = stats.kruskal(class_a, class_b, class_c)

print(f"H statistic: {statistic:.4f}")
print(f"P-value: {p_value:.4f}")

Python output

Python 출력

p-값이 0.05보다 작으므로, 최소 한 반의 점수가 다른 반들과 다르다는 의미입니다. 다만 어떤 반이 다른지는 알려주지 않습니다. 이를 알아보려면 사후 검정이 필요하며, 다음 섹션에서 설명합니다.

R에서의 Kruskal-Wallis 검정

Python과 마찬가지로 R에도 이 검정을 위한 내장 함수가 있습니다. 같은 시험 점수 사례를 사용하겠습니다.

# Exam scores
class_a <- c(78, 85, 90, 72, 88)
class_b <- c(65, 70, 68, 74, 60)
class_c <- c(88, 92, 95, 85, 91)

# Combine
scores <- c(class_a, class_b, class_c)
groups <- factor(rep(c("A", "B", "C"), each = 5))

# Run the test
kruskal.test(scores ~ groups)

R output

R 출력

출력은 Python과 동일합니다. 동일한 H 통계량과 p-값이 나옵니다. p < 0.05이면 귀무가설을 기각하고, 최소 한 집단이 다르다고 결론 내립니다.

Kruskal-Wallis 결과 해석 방법

Kruskal-Wallis 검정의 귀무가설은 모든 집단이 동일한 분포를 가진다는 것입니다. p-값이 이를 기각할지 여부를 알려줍니다. 해석은 다음과 같습니다:

  • p < 0.05: 최소 한 집단이 다른 집단과 다릅니다. 귀무가설을 기각합니다
  • p >= 0.05: 집단 간 차이가 있다고 볼 강한 근거가 없습니다. 귀무가설을 기각하지 않습니다

0.05 임계값은 관례입니다. 분야나 분석의 중요도에 따라 0.01처럼 더 엄격하거나 0.10처럼 더 느슨한 값을 사용할 수 있습니다.

이 검정은 어떤 집단이 다른지까지는 알려주지 않습니다. 유의미한 결과는 모든 집단이 같지는 않다는 뜻일 뿐입니다. 어느 쌍이 차이를 만드는지 확인하려면 사후 검정이 필요합니다.

Kruskal-Wallis 이후의 사후 검정

이 검정은 최소 한 집단이 다르다는 사실만 알려줄 뿐, 어떤 집단이 실제로 다른지 알려주지 않습니다. 세 집단에서 p < 0.05라면 A 대 B, A 대 C, B 대 C 또는 그 조합일 수 있습니다. 이러한 쌍별 비교를 위해 사후 검정을 수행해야 합니다.

Dunn 검정이 가장 흔한 선택입니다. 모든 집단 간 쌍별 비교를 수행하고, 다중 비교를 고려해 p-값을 보정합니다. 보정 없이 진행하면 거짓 양성 가능성이 높아집니다. 비교를 많이 할수록 우연히 "유의"하다는 결과를 찾을 위험이 커집니다.

Python에서의 Dunn 검정

이 작업에는 scikit_posthocs 라이브러리가 필요합니다. 없다면 pip install scikit-posthocs로 설치하세요.

그다음 계산은 간단합니다:

import scikit_posthocs as sp
import pandas as pd

# Same exam scores as before
class_a = [78, 85, 90, 72, 88]
class_b = [65, 70, 68, 74, 60]
class_c = [88, 92, 95, 85, 91]

# Combine
scores = class_a + class_b + class_c
groups = ["A"] * 5 + ["B"] * 5 + ["C"] * 5

df = pd.DataFrame({"score": scores, "group": groups})

# Run the test
result = sp.posthoc_dunn(df, val_col="score", group_col="group", p_adjust="bonferroni")
print(result)

Dunn’s test in Python

Python에서의 Dunn 검정

각 셀은 해당 쌍의 보정된 p-값을 보여줍니다. 여기서는 B 대 C(p = 0.004)만 0.05 임계값을 넘습니다. 따라서 이 두 집단은 다릅니다. A 대 B(p = 0.167)와 A 대 C(p = 0.607)는 유의하지 않으므로, A반은 다른 두 반과 통계적으로 차이가 없습니다.

R에서의 Dunn 검정

먼저 필요하다면 install.packages("dunn.test") 명령으로 라이브러리를 설치합니다:

library(dunn.test)

# Same exam scores as before
class_a <- c(78, 85, 90, 72, 88)
class_b <- c(65, 70, 68, 74, 60)
class_c <- c(88, 92, 95, 85, 91)

scores <- c(class_a, class_b, class_c)
groups <- factor(rep(c("A", "B", "C"), each = 5))

# Run the test
dunn.test(scores, groups, method = "bonferroni")

Dunn’s test in R

R에서의 Dunn 검정

예상대로 결과는 Python과 일치합니다. B 대 C만 유의하며, A 대 B와 A 대 C는 유의하지 않습니다. Kruskal-Wallis 검정에서 감지된 차이는 B반과 C반이 만든 것입니다.

Kruskal-Wallis 검정의 가정

Kruskal-Wallis 검정은 ANOVA보다 유연하지만, 실행 전에 확인해야 할 세 가지 가정이 있습니다:

  • 표본의 독립성: 한 집단의 관측치가 다른 집단의 관측치에 영향을 주지 않아야 합니다. 짝지어진 자료나 반복측정이면 적절하지 않습니다
  • 서열형 또는 연속형 데이터: 순위를 매길 수 있는 데이터가 필요합니다. 명목형 범주(색상, 라벨 등)는 순위를 매길 수 없어 사용할 수 없습니다
  • 유사한 분포 모양: 중앙값 비교로 해석하려면 집단 간 분포 모양이 대략 유사해야 합니다. 모양이 많이 다르면 분포 비교는 가능하지만 중앙값 해석은 성립하지 않습니다

첫 두 가정을 위반하면 검정 결과는 타당하지 않습니다. 세 번째 가정은 다소 유연하여, 검정 실행 가능성보다는 결과 해석 방식에 영향을 줍니다.

Kruskal-Wallis 검정을 사용하지 말아야 할 때

다음 세 가지 경우에는 다른 검정이 더 적합합니다:

  • 데이터가 짝지어졌거나 반복측정인 경우: 동일한 대상이 여러 집단에 걸쳐 나타난다면 Friedman 검정을 사용하세요. 종속 표본을 위한 비모수 대안입니다. 짝지어진 데이터에 Kruskal-Wallis를 적용하면 관측치 간 관계를 무시해 잘못된 결론에 이를 수 있습니다
  • ANOVA 가정을 충족하는 경우: 데이터가 정규분포이고 분산이 대략 유사하다면 ANOVA가 더 좋습니다. 통계적 검정력이 더 높아 실제 차이를 더 잘 탐지합니다
  • 표본 크기가 큰 경우: 큰 표본에서는 데이터가 완전한 정규성이 아니어도 모수 방법이 잘 작동하는 경향이 있습니다. 중심극한정리가 작동하며, ANOVA가 순위 기반 접근보다 더 신뢰할 수 있는 결과를 제공합니다. 집단당 수백 혹은 수천 개의 관측치가 있다면 Kruskal-Wallis는 적합하지 않습니다

결론

Kruskal-Wallis 검정은 ANOVA 같은 검정이 요구하는 정규분포를 따르지 않는 데이터에서 세 집단 이상 독립 집단을 비교할 때 사용합니다. 원시값 대신 순위에 기반하기 때문에 가능합니다.

그렇다고 ANOVA를 대체하는 것은 아닙니다. 데이터가 정규적이면 ANOVA가 통계적 검정력이 더 높아 더 적합합니다. 반면 데이터가 짝지어진 경우에는 Friedman 검정을 사용하세요. 늘 그렇듯 올바른 검정은 데이터에 달려 있습니다.

조건이 맞을 때 Kruskal-Wallis 검정은 신뢰할 수 있고 간단한 선택입니다. 검정을 실행하고 p-값을 확인한 뒤, 어느 집단이 차이를 만드는지 알아야 한다면 Dunn 검정으로 후속 분석을 진행하세요.

통계 지식이 조금 가물가물하신가요? Introduction to Statistics 과정을 수강하고 하루 만에 감을 되찾아 보세요.

Kruskal-Wallis 검정 FAQ

Kruskal-Wallis 검정은 무엇에 사용하나요?

Kruskal-Wallis 검정은 데이터가 정규분포를 따른다고 가정할 수 없을 때 세 개 이상의 독립 집단을 비교하는 데 사용됩니다. 원시값 대신 순위에 기반해 작동하는 ANOVA의 비모수적 대안입니다. 분포가 치우쳐 있거나 데이터가 서열형일 때 유용합니다.

Kruskal-Wallis 결과가 유의미하다는 것은 무엇을 뜻하나요?

유의미한 결과(일반적으로 p < 0.05)는 최소 한 집단이 다른 집단과 다르다는 의미입니다. 어떤 집단이 다른지는 알려주지 않습니다. 어느 쌍이 차이를 만드는지 알기 위해서는 Dunn 검정 같은 사후 검정을 수행해야 합니다.

Kruskal-Wallis 검정의 가정은 무엇인가요?

검정은 표본의 독립성을 요구합니다. 즉, 한 집단의 관측치가 다른 집단의 관측치에 영향을 주면 안 됩니다. 데이터는 순위를 매길 수 있는 서열형 또는 연속형이어야 합니다. 중앙값 비교로 해석하려면 집단 간 분포 모양이 유사해야 합니다.

Kruskal-Wallis 검정과 Mann-Whitney U 검정의 차이는 무엇인가요?

Mann-Whitney U 검정은 두 개의 독립 집단을 비교하고, Kruskal-Wallis 검정은 그 접근을 세 집단 이상으로 확장합니다. 둘 다 순위 데이터에 기반하며 정규성을 가정하지 않습니다. 집단이 두 개뿐이라면 Mann-Whitney U가 적합하고, Kruskal-Wallis는 다집단에 해당하는 대안입니다.

Kruskal-Wallis 이후 Dunn 검정은 언제 사용하나요?

Kruskal-Wallis 결과가 유의하고, 어떤 집단 쌍이 다른지 알아야 할 때 Dunn 검정을 사용하세요. 모든 집단 간 쌍별 비교를 수행하고 p-값을 보정해 거짓 양성 위험을 줄입니다. Python에서는 scikit_posthocs.posthoc_dunn()을, R에서는 dunn.test 패키지를 사용하면 됩니다.

주제

DataCamp로 학습하세요

courses

R로 시작하는 통계학 입문

4
131.8K
통계 기술을 향상시키고 데이터를 수집, 분석하며 정확한 결론을 도출하는 방법을 배우세요.
자세히 보기Right Arrow
강좌 시작
더 보기Right Arrow