Cute Hello Kitty 3
본문 바로가기
Data/통계

정규성 검정 / Shapiro-Wilk / Anderson-Darling / Kolmogorov–Smirnov / Q-Q Plot

by 민 채 2025. 4. 4.
 
 
 

 

정규성 검정(Normality Test) 이란?

정규성 검정은 데이터가 정규분포를 따르는지를 검정하는 과정입니다.
많은 통계 기법(Z-test, t-test 등)은 정규분포를 전제로 하기 때문에, 분석 전에 정규성을 검정하는 것은 매우 중요합니다.


주요 정규성 검정 방법

방법 특징 추천 상황
Shapiro-Wilk 소표본에 적합, 널리 사용됨 n ≤ 50에 특히 강력
Anderson-Darling 분포의 꼬리까지 민감 정밀한 정규성 검정 필요 시
Kolmogorov–Smirnov 이론 분포와의 차이 검정 대체로 덜 민감, 일반적인 확인용
Q-Q Plot 시각적 확인 간단한 탐색적 분석 시

 

✍️ 실전 팁

  • 여러 정규성 검정을 함께 사용하는 것이 좋다.
  • QQ Plot 을 통해 시각적으로 먼저 확인 한 뒤, 추가 검정을 수행한다.
  • 정규성이 없다면? →  비모수 검정 또는 데이터 변환(log, sqrt 등) 고려

Q-Q Plot

Q-Q Plot 이란?

Q-Q Plot (Quantile-Quantile Plot) 은 이름 그대로

"두 분포의 분위수(Quantile)를 서로 비교한 그래프" 입니다.

분위수(Quantile)란?
데이터를 오름차순으로 정렬했을 때,
특정 비율에 해당하는 위치의 값을 말합니다.

예시:
- 0.5 분위수: 중앙값
- 0.25 분위수: 1사분위수 (Q1)
- 0.75 분위수: 3사분위수 (Q3)

쉽게 말해,

“내 데이터가 특정 분포(보통은 정규분포)를 잘 따르고 있는지 시각적으로 확인하는 방법” 이라고 할 수 있습니다.

 

작동 방식

 

  1. 데이터를 정렬 (오름차순으로)
  2. 비교하려는 이론 분포의 분위수를 구함
  3. 내 데이터의 값을 점으로 찍어 그래프에 표시
  4. 만약 두 분포가 비슷하다면?
    • 점들이 대각선 직선 위에 가지런히 놓여있게 된다.

 

# 나의 데이터가 정규분포를 따를까?
x = [155, 126, 27, 82, 115, 140, 73, 92, 110, 134]

np.percentile(x, 25)  # 84.5
norm.ppf(0.25, loc=np.mean(x), scale=x.std(ddof=1))  # 79.8

np.percentile(x, 50)  # 112.5
norm.ppf(0.50, loc=np.mean(x), scale=x.std(ddof=1))  # 105.4

np.percentile(x, 75)  # 132.0
norm.ppf(0.75, loc=np.mean(x), scale=x.std(ddof=1))  # 131.0

제가 임의로 만든 데이터 x를 파이썬 코드를 사용해서 정규분포와 비교해보겠습니다.

  • 0.25분위수
    • 내 데이터: 84.5
    • 정규 분포: 79.8
  • 0.5 분위수
    • 내 데이터: 112.5
    • 정규 분포: 105.4
  • 0.75 분위수
    • 내 데이터: 132
    • 정규 분포: 131

이렇게 보면 얼추 정규분포를 따르고 있는것 같지만 너무 주관적이고 애매합니다. 이를 QQ Plot 으로 그려서 확인해봅시다.

 

 

QQ Plot

 

파란 색 점이 제가 만든 데이터이고, 빨간색 선이 정규분포입니다. 얼추 빨간선에 붙어 있는 추세가 보입니다. 이러한 추세를 시각적으로 먼저 확인하고 수치 기반의 추가적인 검정을 진행하면 좋습니다.

 


Shapiro-Wilk 검정

이제 Shapiro-wilk 검정을 사용해서 정규성을 검정해 보겠습니다. 내 데이터가 정규분포를 따르는 지? 를 판단해보겠습니다.

주요 특징

 

  • 소표본(3 ≤ n ≤ 50)에서 특히 강력
  • p-value를 기준으로 판단
  • SciPyR에서도 기본 지원
  • 이상치에 민감할 수 있음

Python 코드

import numpy as np
from scipy.stats import shapiro

# 정규분포 데이터 생성
x = np.random.normal(loc=0, scale=1, size=30)

# Shapiro-Wilk 검정 실행
stat, p = shapiro(x)

print(f"Shapiro-Wilk 통계량 = {stat:.4f}")
print(f"p-value = {p:.4f}")

# 결과 해석
if p < 0.05:
    print("정규성을 기각합니다. 정규분포가 아닐 가능성 있음")
else:
    print("귀무가설을 기각하지 못합니다. 정규분포일 수 있음")

 

파이썬에 scipy 모듈에 shapiro wilk 검정이 구현되어 있습니다. 이를 활용해서 간단히 검정 통계량과 p-value 값을 얻을 수 있습니다.

p-value 값이 0.05 보다 작으면 귀무가설을 기각합니다. 즉, 정규분포를 따른다고 할 수 없습니다.

 

 

 


Kolmogorov–Smirnov 검정 (K-S test)

내 데이터가 특정 분포를 따르는 지 검정하는 방법 중 하나입니다.

특히, “내 데이터의 누적분포가 특정 이론 분포(예: 정규분포)의 누적분포와 얼마나 다른가?”
를 측정하는 정규성 검정법입니다.

구현 원리

 

  • 실제 데이터에서 구한 누적분포함수 (ECDF)
  • 비교 대상인 이론 누적분포함수 (CDF)
    이 둘 사이의 최대 차이를 계산해서 판단합니다.
$$ D = \max_x \left| F_n(x) - F(x) \right| $$ - $F_n(x)$: 실제 데이터의 누적분포 (경험적 CDF)
- $F(x)$: 정규분포 또는 지정 분포의 누적분포 (이론 CDF)
- $D$: 두 분포 간 최대 거리


즉, 직관적으로 보면

  • k-s 검정은 두 분포의 거리 차이가 얼마나 큰지? 를 확인합니다.
  • 이 거리 차이(D)가 크면 정규성이 없고, 작으면 정규성이 있습니다.

 

시각화

ecdf 그래프
ECDF

 

파란 선은 실제 데이터 기반의 ECDF 이고, 빨간 선은 정규분포 기반의 CDF 입니다. 

→ 두 선의 차이가 바로 K-S 검정 통계량 D로 이어집니다.

 

Python 코드

K-S 검정은 위에서 시각화한 ECDF와 이론 분포의 CDF 사이의 최대 거리(D)를 계산해서 정규성을 검정합니다. 이를 파이썬 코드로 구현하면 간단히 사용할 수 있습니다.

from scipy.stats import kstest

stat, p = kstest(data_x, 'norm', args=(data_x.mean(), data_x.std(ddof=1)))
print(f"K-S 통계량 = {stat:.4f}")
print(f"p-value = {p:.4f}")

 

Kolmogorov–Smirnov(K-S) 검정의 주요 특징

항목 설명
목적 데이터가 특정 분포(보통 정규분포)를 따르는지 확인
방식 경험적 누적분포(ECDF)와 이론 CDF 간 최대 거리(D)를 계산
통계량 D = 최대 거리
입력 필요 비교할 분포의 평균과 표준편차 (args=(mean, std))
유의미한 결과 p-value < 0.05 면 정규분포가 아님
장점 빠르고 간단함, 다양한 분포 비교 가능 (정규분포 외에도 가능)
단점 작은 표본에서는 덜 민감, 중심보다 꼬리 차이에 덜 민감

 

🔍 K-S 검정은 이런 상황에서 유용해요

  • 데이터가 많고 빠르게 정규성 검정이 필요할 때
  • 단순히 특정 분포와의 전체 분포 모양이 비슷한 지 보고싶을 때
  • 정규성 뿐 아니라 지수분포, 균등분포 등과 비교할 때

 


Anderson-Darling 검정

샘플 데이터가 특정 분포(주로 정규분포)를 따르는지를 검정하는 통계적 방법입니다.
Kolmogorov–Smirnov 검정을 개선한 버전으로, 꼬리 부분 차이에도 민감합니다.

검정 통계량 (공식)

$$ A^2 = -n - \frac{1}{n} \sum_{i=1}^{n} (2i - 1) \left[ \ln F(x_i) + \ln \left(1 - F(x_{n+1-i})\right) \right] $$ - $n$: 표본 크기
- $F(x)$: 비교할 이론 누적분포함수 (예: 정규분포의 CDF)
- $x_i$: 정렬된 표본 값

 

  • Kolmogorov-Smirnov 검정처럼 누적분포함수(CDF)를 비교합니다.
  • 하지만 단순히 최대 거리만 보는 K-S 검정과 달리,
    분포의 꼬리(tail) 부분까지 민감하게 차이를 반영합니다.

 

Python 코드

from scipy.stats import anderson
import numpy as np

# 예시: 정규분포 데이터
x = np.random.normal(loc=0, scale=1, size=100)

# Anderson-Darling 정규성 검정
result = anderson(x, dist='norm')

print("Anderson-Darling 통계량:", result.statistic)
print("임계값들:", result.critical_values)
print("유의수준들:", result.significance_level)

# 결과 출력
Anderson-Darling 통계량: 0.278
임계값들: [0.554 0.632 0.759 0.885 1.053]
유의수준들: [15. 10. 5. 2.5 1.]

# 결과 판별
if result.statistic < result.critical_values[2]:  # 5% 수준
    print("정규성을 만족함")
else:
    print("정규성이 없다")

Anderson-Darling 검정의 단점은, p-value 를 모듈에서 직접 제공하지 않는다는 것입니다.

그래서 임계값과 직접 비교하는 과정을 거쳐야합니다.

 

다양한 정규성 검정 방법 비교 

항목 Shapiro-Wilk K-S Anderson-Darling
목적 정규성 검정 전용 분포간 차이 검정 정규성 + 꼬리 비교
p-value 제공 O O X (임계값 비교)
꼬리 민감도 낮음 높음
정밀도 높음 낮음 높음
추천 표본 크기 3~5000 제한 없음 제한 없음
다양한 분포 검정 X O O