콘텐츠로 이동

분산분석의 가정

일원배치 분산분석 모형은 각 관측값을 \(Y_{ij} = \mu_i + \epsilon_{ij}\)로 분해한다. 여기서 \(\mu_i\)는 집단 \(i\)의 모평균이고 \(\epsilon_{ij}\)는 무작위 오차항이다. F-검정의 타당성은 이 오차항에 부과되는 조건들에 달려 있다. 각 가정이 왜 필요한지, 그리고 어긋나면 무엇이 잘못되는지를 이해하는 일은 실제 자료에 분산분석을 적용하기 전에 꼭 필요하다. 이 페이지는 네 가지 핵심 가정과 그 결과를 요약하며, 이 절의 나머지 페이지들이 각각에 대한 구체적인 진단 절차를 제공한다.

가정 요약

분산분석 F-검정의 바탕이 되는 네 가정은 다음과 같다:

  1. 정규성: 오차항 \(\epsilon_{ij}\)가 각 집단 안에서 정규분포를 따라 \(Y_{ij} \mid \text{집단 } i \sim N(\mu_i, \sigma^2)\)이다. 실제로는 관측할 수 없는 오차를 추정하는 잔차 \(e_{ij} = Y_{ij} - \bar{Y}_{i\cdot}\)를 살펴 평가한다. 진단 방법은 정규성 확인을 보라.

  2. 독립성: 관측값들이 통계적으로 서로 독립이다. 이 가정은 사후에 검정하기보다 올바른 실험 설계(무작위 표집과 무작위 배정)로 확보한다. 자세한 내용은 독립성 확인을 보라.

  3. 등분산성: 모분산 \(\sigma^2\)이 모든 집단에서 같다. 집단 분산이 다르면 합동 평균제곱오차가 더 이상 하나의 공통 분산을 추정하지 못하고 F-비를 믿을 수 없게 된다. Levene 검정과 관련 진단은 등분산성 확인을 보라.

  4. 선형성: 설명변수와 반응 사이의 관계가 선형이다. 이 가정은 공분산분석처럼 분산분석 모형에 연속형 공변량이 들어갈 때 관련된다. 순수하게 범주형인 요인만 있으면 선형성은 자동으로 만족된다. 지침은 선형성 확인을 보라.

가정이 중요한 이유

F-검정통계량이 귀무가설 아래에서 정확히 \(F\)-분포를 따르는 것은 정규성, 독립성, 등분산성이 모두 성립할 때뿐이다. 위반은 이 기준분포를 왜곡하여 잘못된 p-값과 신뢰할 수 없는 판정으로 이어진다.

  • 정규성. 잔차가 정규가 아니면 F-통계량의 표본분포가 이론적 \(F\)-분포에서 벗어나며, 특히 표본이 작을 때 그렇다. 표본이 커지면 중심극한정리가 어느 정도 로버스트성을 주지만, 집단당 관측이 20–30개 미만이면 치우침이나 두꺼운 꼬리가 여전히 제1종 오류율을 부풀리거나 줄일 수 있다.

  • 독립성. 관측값 사이의 의존성은 가장 치명적인 위반이다. 양의 상관은 유효 자유도를 명목값보다 낮추어 표준오차 추정을 너무 작게 만든다. 그 결과 제1종 오류율이 부풀려져 명목 \(\alpha\) 수준이 시사하는 것보다 훨씬 자주 기각하게 된다.

  • 등분산성. 집단 분산이 다르면 합동분산 추정값이 분산이 큰 집단을 과대 대표한다. 그러면 작은 집단의 분산이 클 때 F-검정이 관대해지고(너무 자주 기각하고), 반대의 경우에는 보수적이 된다(너무 드물게 기각한다). 분산을 합동하지 않는 Welch 분산분석이 로버스트한 대안이 된다.

  • 선형성. 연속형 공변량이 있고 참 관계가 비선형이면 모형이 집단 평균을 체계적으로 잘못 추정한다. 잔차 그림에 특유의 곡선 패턴이 나타나 이런 오설정을 알려준다.

네 가정을 나란히 적어 놓으면 똑같이 중요해 보이지만 위반의 대가는 결코 같지 않다. 각 가정을 하나씩만 깨뜨린 자료를 만들고, 평균이 모두 같은 상태에서 고전 \(F\)-검정이 실제로 얼마나 기각하는지 반복 8,000회로 재어 보았다.

가정마다 위반의 대가가 다르고, 맞는 처방을 쓰면 회복된다

정규성 위반이 가장 덜 위험하다. 대수정규 자료에서 고전 \(F\)의 실제 기각률은 \(0.033\)으로 명목 \(0.05\)보다 오히려 작다. 어긋나는 방향이 보수적이므로 없는 차이를 만들어 내지는 않는다. 반면 등분산이 깨지면 \(0.079\)로 올라가고, 거기에 불균형(\(n = (20, 20, 5)\), 분산이 가장 큰 집단이 가장 작다)이 더해지면 \(0.286\)까지 치솟는다. 독립성이 깨진 경우(집단마다 군집 6개 \(\times\) 5명, 급내상관 \(0.3\))도 \(0.262\)다. 평균이 정확히 같은데 네 번에 한 번 이상 "차이가 있다"고 판정한다.

초록 막대가 각 위반에 맞는 처방을 썼을 때의 결과다. 이분산에는 웰치 분산분석, 군집 자료에는 군집 평균을 분석단위로 삼는 분산분석을 적용하면 \(0.048\)–\(0.059\)로 모두 제자리에 돌아온다. 문제는 검정이 무너진다는 것이 아니라 틀린 검정을 쓴다는 것이다.

그렇다고 정규성을 무시해도 좋다는 뜻은 아니다. 오른쪽 그림이 그 이유다. 평균을 \(0,\ 0.8,\ 1.6\)으로 벌려 놓고 검정력을 재면, 정규 자료에서는 \(F\)가 \(0.97\)로 크러스컬–월리스의 \(0.96\)보다 근소하게 앞선다. 그런데 대수정규에서는 \(0.57\) 대 \(0.93\), 코시에서는 \(0.08\) 대 \(0.46\)으로 완전히 역전된다. 정규성 위반이 앗아 가는 것은 제1종 오류율이 아니라 검정력이다. 있는 차이를 못 찾는 쪽으로 손해를 보므로 위 왼쪽 그림에는 나타나지 않는다. 위 진단 작업 흐름이 독립성과 등분산을 먼저 보고 정규성을 나중에 보는 것은 이 비대칭 때문이다.

예시: 분산이 다를 때 F-검정에 미치는 영향

\(n_1 = n_2 = n_3 = 10\)이고 모평균이 모두 같은(\(\mu_1 = \mu_2 = \mu_3 = 0\)) 세 집단을 생각하자. 등분산(\(\sigma_1^2 = \sigma_2^2 = \sigma_3^2 = 1\)) 아래에서 F-검정은 기대대로 \(\alpha = 0.05\) 수준에서 약 5%의 비율로 기각한다.

이제 \(\sigma_1^2 = 1\), \(\sigma_2^2 = 1\), \(\sigma_3^2 = 9\)라고 하자(집단 3의 분산이 훨씬 크다). 모평균이 여전히 모두 같은데도 표준 F-검정은 5%가 아니라 대략 8–10%의 비율로 기각한다. 합동분산 추정값이 왜곡되기 때문이다. 각 집단의 분산을 따로 추정하는 Welch 분산분석은 이 상황에서도 올바른 5% 기각률을 유지한다.

이 예는 표준 분산분석 F-검정을 해석하기 전에 등분산성을 확인해야 하는 이유를 보여준다. 분산이 크게 다르면 검정이 허위 "유의" 결과를 낼 수 있다.

진단 작업 흐름

가정 확인의 체계적인 접근은 다음과 같이 진행된다:

  1. 분산분석 모형을 적합하고 잔차 \(e_{ij} = Y_{ij} - \bar{Y}_{i\cdot}\)를 계산한다.
  2. 연구 설계를 검토하여 독립성을 확인한다. 관측값이 상관될 수 있다면(예: 반복측정, 시계열 자료) 혼합효과 모형이나 반복측정 분산분석을 대신 고려한다.
  3. Levene 검정이나 잔차 대 적합값 그림으로 등분산성을 확인한다. 분산이 다르면 Welch 분산분석으로 옮기거나 분산 안정화 변환을 적용한다.
  4. 잔차의 Q-Q 그림과 Shapiro-Wilk 검정으로 정규성을 확인한다. 표본이 크면(집단당 \(n > 30\)) 어느 정도의 비정규성은 대체로 감내할 만하다.
  5. 모형에 연속형 공변량이 있으면 선형성을 확인한다. 산점도와 부분잔차 그림으로 곡률을 탐지한다.

가정이 하나 이상 어긋나면 어느 가정이 무너졌는지에 따라 적절한 처방이 달라진다. 가정 위반의 처리 페이지가 변환, 비모수 대안(Kruskal-Wallis), 로버스트 방법(Welch 분산분석)을 아우르는 판단 틀을 제공한다.

연습문제

연습문제 1. 일원배치 분산분석의 표준적인 세 가정을 나열하고, 각각이 어긋나면 F-검정에 무슨 일이 생기는지 설명하라.

풀이

세 가정은 다음과 같다:

  1. 독립성: 집단 안에서도, 집단 사이에서도 관측값이 독립이다. 위반(예: 반복측정, 군집 자료)은 유효 표본크기가 명목 \(n\)보다 작아지므로 제1종 오류율을 부풀린다.

  2. 정규성: 잔차(또는 동등하게 각 집단 안의 관측값)가 정규분포를 따른다. 표본이 크면 중심극한정리 덕분에 어느 정도의 위반은 감내할 만하지만, 심한 치우침이나 두꺼운 꼬리는 특히 집단 크기가 작거나 서로 다를 때 F-분포를 왜곡할 수 있다.

  3. 등분산성: 모든 집단의 모분산 \(\sigma^2\)이 같다. 분산이 다르면 큰 분산이 작은 집단에 있는지 큰 집단에 있는지에 따라 F-통계량이 부풀거나 줄어든다. 이 가정이 무너지면 Welch 분산분석이 로버스트한 대안이다.

연습문제 2. 분산의 동질성에 대한 Levene 검정이 p-값 0.02를 주었다. 표준 분산분석을 그대로 진행해야 하는가? 대안을 제시하라.

풀이

Levene 검정의 p-값 0.02는 5% 수준에서 등분산 가정에 반하는 증거이다. 표준 분산분석을 그대로 진행하면 F-검정이 잘못될 위험이 있다. 큰 분산이 작은 집단에 있으면 F-검정이 관대해지고(거짓 양성이 많아지고), 큰 집단에 있으면 보수적이 된다(검정력을 잃는다).

대안:

  1. Welch 분산분석: 등분산을 가정하지 않고 자유도를 그에 맞게 조정한다. 권장되는 기본 선택이다.
  2. 변환: 분산 안정화 변환(예: 로그, 제곱근)으로 분산을 고르게 만든 뒤 표준 분산분석을 수행한다.
  3. 비모수 검정: 정규성이나 등분산을 가정하지 않는 Kruskal-Wallis 검정을 쓴다.

연습문제 3. 표본이 크고 균형 잡혀 있을 때 분산분석이 정규성 가정의 완만한 위반에 로버스트하다고 보는 이유를 설명하라.

풀이

분산분석의 로버스트성은 두 가지에서 나온다:

  1. 중심극한정리: \(n_j\)가 어느 정도 크면(흔히 \(n_j \geq 20\)–30이면 충분하다) 개별 관측값이 정규가 아니어도 집단 평균 \(\bar{X}_j\)는 근사적으로 정규를 따른다. F-통계량은 집단 평균을 비교하므로 중요한 것은 평균의 정규성이다.

  2. 균형 설계: 집단 크기가 같으면(\(n_1 = n_2 = \dots = n_k\)) 합동분산 추정값이 각 집단에 같은 가중치를 주므로 F-검정이 분산 차이에 로버스트하다. 불균형 설계에서는 F-검정이 이분산에 민감해진다.

다만 분산분석은 작은 표본에서의 두꺼운 꼬리, 심한 치우침, 이상점에는 로버스트하지 않다. 이런 경우에는 변환이나 비모수 대안을 고려해야 한다.

연습문제 4. 분산분석 모형을 적합한 뒤 잔차 그림으로 정규성과 등분산성 가정을 평가하는 방법을 기술하라.

풀이

분산분석 모형을 적합한 뒤 잔차 \(e_{ij} = x_{ij} - \bar{x}_j\)(관측값에서 집단 평균을 뺀 값)를 계산한다. 그다음:

  1. 정규성 확인: 잔차를 이론적 정규분위수에 대해 Q-Q 그림으로 그린다. 점들이 대략 직선을 따라 놓이면 정규성 가정이 합당하다. 체계적인 곡률은 치우침을, S자 형태의 이탈은 두꺼운 꼬리를 뜻한다. 잔차에 Shapiro-Wilk 검정을 적용할 수도 있다.

  2. 등분산성 확인: 잔차를 적합값(집단 평균)이나 집단 표시에 대해 그린다. 잔차의 흩어짐이 집단마다 대략 같아야 한다. 깔때기 모양(평균이 커질수록 흩어짐이 커짐)은 이분산을 시사한다. 집단별 잔차분산을 수치로 비교하거나 Levene 검정을 쓸 수도 있다.

  3. 독립성 확인: 자료에 자연스러운 순서(시간, 공간)가 있으면 그 순서대로 잔차를 그려 패턴을 확인한다. 잔차의 자기상관은 독립성 위반을 나타낸다.

연습문제 5. 본문의 예시는 이분산 아래에서 \(F\) 검정이 "8–10%" 비율로 기각한다고 말한다. 직접 재어 확인하고, 불균형이 더해지면 어떻게 되는지 보여라.

풀이
import numpy as np
from scipy import stats

def welch_p(gs):
    n = np.array([len(g) for g in gs], float)
    m = np.array([g.mean() for g in gs])
    v = np.array([g.var(ddof=1) for g in gs])
    k = len(n)
    w = n / v
    W = w.sum()
    mt = (w * m).sum() / W
    lam = ((1 - w / W)**2 / (n - 1)).sum()
    F = ((w * (m - mt)**2).sum() / (k - 1)
         / (1 + 2 * (k - 2) / (k**2 - 1) * lam))
    return stats.f.sf(F, k - 1, (3 / (k**2 - 1) * lam)**-1)

rng = np.random.default_rng(1001)
B = 20_000

print("균형 설계 n = (10, 10, 10)")
for lab, sds in [("등분산 σ²=(1,1,1)", [1, 1, 1]),
                 ("본문 σ²=(1,1,9)", [1, 1, 3])]:
    a = b = 0
    for _ in range(B):
        gs = [rng.normal(0, s, 10) for s in sds]
        a += stats.f_oneway(*gs).pvalue < 0.05
        b += welch_p(gs) < 0.05
    print(f"  {lab:20s} 표준 F {a / B:.4f}   웰치 {b / B:.4f}")

print("\n불균형 n = (20, 20, 5), σ²=(1,1,9)")
for lab, ns, sds in [("역페어링", [20, 20, 5], [1, 1, 3]),
                     ("정페어링", [5, 20, 20], [1, 1, 3])]:
    a = b = 0
    for _ in range(B):
        gs = [rng.normal(0, s, n) for n, s in zip(ns, sds)]
        a += stats.f_oneway(*gs).pvalue < 0.05
        b += welch_p(gs) < 0.05
    print(f"  {lab:20s} 표준 F {a / B:.4f}   웰치 {b / B:.4f}")
균형 설계 n = (10, 10, 10)
  등분산 σ²=(1,1,1)       표준 F 0.0498   웰치 0.0472
  본문 σ²=(1,1,9)        표준 F 0.0801   웰치 0.0534

불균형 n = (20, 20, 5), σ²=(1,1,9)
  역페어링                 표준 F 0.2858   웰치 0.0587
  정페어링                 표준 F 0.0328   웰치 0.0568

본문의 주장이 확인된다. 균형 설계에서 0.0801로 "8–10%" 범위의 아래쪽이다.

그런데 불균형이 더해지면 0.2858이 된다. 명목의 5.7배다.

설계 표준 \(F\) 웰치
등분산·균형 0.050 0.047
이분산·균형 0.080 0.053
이분산·역페어링 0.286 0.059
이분산·정페어링 0.033 0.057

균형 설계가 이분산을 상당히 막아 준다. 0.080은 이상적이지 않지만 재앙은 아니다. 불균형이 더해질 때 무너진다.

역페어링과 정페어링의 정의.

배치 결과
역페어링 작은 집단에 큰 분산 오류율 폭증
정페어링 작은 집단에 작은 분산 지나치게 보수적

정페어링의 0.0328도 문제다. 거짓 양성은 줄지만 검정력을 잃는다. 실제 차이를 놓친다.

실무 함의 셋.

  1. 설계 단계에서 균형을 맞추는 것이 이분산에 대한 가장 값싼 방어다.
  2. 불균형이 불가피하면 웰치를 쓴다(모든 경우 0.047~0.059).
  3. "분산비가 4배 이내면 괜찮다"는 경험칙은 균형 설계에만 해당한다.

본문을 이렇게 고쳐 읽자. "분산이 다르면 8–10% 기각한다"가 아니라 "균형이면 8%, 불균형이면 29%까지 간다"가 정확하다.

연습문제 6. 본문은 "독립성이 가장 치명적인 위반"이라고 말한다. 세 가지 위반을 같은 척도로 재어 이 순위를 확인하라.

풀이
import numpy as np
from scipy import stats

rng = np.random.default_rng(606)
B = 8_000

def ar1(n, rho, rng):
    """1차 자기상관을 가진 계열. 주변분산은 1 로 맞춘다."""
    e = rng.normal(0, 1, n)
    x = np.empty(n)
    x[0] = e[0] / np.sqrt(1 - rho**2)
    for t in range(1, n):
        x[t] = rho * x[t - 1] + e[t]
    return x

cases = {
    "기준 (모든 가정 성립)": lambda: [rng.normal(0, 1, 15) for _ in range(3)],
    "등분산 위반 (σ=1,1,3)": lambda: [rng.normal(0, s, 15) for s in [1, 1, 3]],
    "등분산 위반 (σ=1,3,5)": lambda: [rng.normal(0, s, 15) for s in [1, 3, 5]],
    "정규성 위반 (지수)": lambda: [rng.exponential(1, 15) - 1 for _ in range(3)],
    "정규성 위반 (로그정규)":
        lambda: [np.exp(rng.normal(0, 1, 15)) - np.exp(.5) for _ in range(3)],
    "독립성 위반 (AR1 ρ=0.3)": lambda: [ar1(15, 0.3, rng) for _ in range(3)],
    "독립성 위반 (AR1 ρ=0.6)": lambda: [ar1(15, 0.6, rng) for _ in range(3)],
}
print("k=3, 집단당 n=15, 균형, 명목 0.05")
print(f"{'상황':>26s} {'표준 F 오류율':>12s}")
for lab, f in cases.items():
    a = sum(stats.f_oneway(*f()).pvalue < 0.05 for _ in range(B))
    print(f"{lab:>26s} {a / B:12.4f}")
k=3, 집단당 n=15, 균형, 명목 0.05
                        상황     표준 F 오류율
             기준 (모든 가정 성립)       0.0548
          등분산 위반 (σ=1,1,3)       0.0720
          등분산 위반 (σ=1,3,5)       0.0670
               정규성 위반 (지수)       0.0408
             정규성 위반 (로그정규)       0.0365
        독립성 위반 (AR1 ρ=0.3)       0.1963
        독립성 위반 (AR1 ρ=0.6)       0.4754

순위가 명확하다.

순위 위반 오류율 명목 대비
1위 독립성 (\(\rho=0.6\)) 0.475 9.5배
2위 독립성 (\(\rho=0.3\)) 0.196 3.9배
3위 등분산 0.067~0.072 1.3~1.4배
4위 정규성 0.037~0.041 0.7~0.8배

독립성 위반이 압도적이다. \(\rho=0.3\)이라는 완만한 상관만으로도 오류율이 네 배가 된다. 자기상관이 유효 표본크기를 줄이는데 검정은 그것을 모르기 때문이다.

\[ n_{\text{유효}}\approx n\cdot\frac{1-\rho}{1+\rho} \]

\(\rho=0.6\)이면 \(n_{\text{유효}}\approx15\times0.25=3.75\)다. 표본 15개가 사실상 4개다.

정규성 위반은 오히려 보수적이다(0.037~0.041). 균형·등분산 설계에서 치우침은 오류율을 낮춘다. 본문의 "부풀리거나 줄일 수 있다"는 서술 중 여기서는 "줄이는" 쪽이다.

등분산 위반이 생각보다 가볍다(0.067~0.072). 이 역시 균형 설계이기 때문이며, 불균형이 더해지면 0.29까지 간다(연습문제 5).

세 위반의 성격이 다르다.

위반 사후 교정 방어책
독립성 거의 불가능 설계(무작위화, 계층 모형)
등분산 쉬움 웰치, 변환
정규성 쉬움 변환, 순열검정, 큰 표본

독립성만 사후에 고칠 수 없다. 자료를 다 모은 뒤 "사실 반복측정이었다"를 알면 혼합효과 모형으로 다시 설계해야 한다. 그래서 설계 단계에서 확보해야 한다.

본문의 순위가 옳다. 다만 "치명적"의 정도가 9.5배임을 수치로 아는 것과 말로만 아는 것은 다르다.

연습문제 7. 본문의 작업 흐름은 "레빈 검정으로 확인하고, 다르면 웰치로 옮긴다"는 2단계 절차다. 이 절차의 실제 오류율을 재어 "항상 웰치"와 비교하라.

풀이
import numpy as np
from scipy import stats

def welch_p(gs):
    n = np.array([len(g) for g in gs], float)
    m = np.array([g.mean() for g in gs])
    v = np.array([g.var(ddof=1) for g in gs])
    k = len(n)
    w = n / v
    W = w.sum()
    mt = (w * m).sum() / W
    lam = ((1 - w / W)**2 / (n - 1)).sum()
    F = ((w * (m - mt)**2).sum() / (k - 1)
         / (1 + 2 * (k - 2) / (k**2 - 1) * lam))
    return stats.f.sf(F, k - 1, (3 / (k**2 - 1) * lam)**-1)

rng = np.random.default_rng(717)
B = 10_000
print(f"{'상황':>24s} {'항상 F':>8s} {'항상 웰치':>9s} "
      f"{'2단계':>8s} {'레빈 기각률':>10s}")
for lab, ns, sds in [
    ("등분산 n=(15,15,15)", [15, 15, 15], [1, 1, 1]),
    ("이분산 n=(15,15,15) σ=(1,1,3)", [15, 15, 15], [1, 1, 3]),
    ("역페어링 n=(20,20,6) σ=(1,1,4)", [20, 20, 6], [1, 1, 4]),
]:
    a = b = c = lev = 0
    for _ in range(B):
        gs = [rng.normal(0, s, n) for n, s in zip(ns, sds)]
        pf = stats.f_oneway(*gs).pvalue
        pw = welch_p(gs)
        pl = stats.levene(*gs, center="median").pvalue
        a += pf < 0.05
        b += pw < 0.05
        lev += pl < 0.05
        c += (pw < 0.05) if pl < 0.05 else (pf < 0.05)   # 2단계 절차
    print(f"{lab:>24s} {a / B:8.4f} {b / B:9.4f} {c / B:8.4f} {lev / B:10.4f}")
                      상황     항상 F     항상 웰치      2단계     레빈 기각률
        등분산 n=(15,15,15)   0.0493    0.0487   0.0495     0.0263
이분산 n=(15,15,15) σ=(1,1,3)   0.0734    0.0471   0.0497     0.9373
역페어링 n=(20,20,6) σ=(1,1,4)   0.3142    0.0551   0.0842     0.8926

역페어링에서 2단계 절차의 오류율이 0.0842다. "항상 웰치"의 0.0551보다 1.5배 나쁘다.

상황 항상 \(F\) 항상 웰치 2단계
등분산 0.049 0.049 0.050
이분산·균형 0.073 0.047 0.050
역페어링 0.314 0.055 0.084

왜 2단계가 나쁜가. 레빈 검정이 10.7%의 경우 이분산을 놓친다(기각률 0.8926). 놓친 그 경우에 표준 \(F\)로 가는데, 표준 \(F\)의 오류율이 0.314다.

\[ 0.8926\times0.055+0.1074\times(\text{놓친 경우의 }F\text{ 오류율})\approx0.084 \]

놓치는 경우가 하필 위험한 경우다. 레빈이 이분산을 놓치는 표본은 우연히 분산이 비슷해 보인 표본인데, 그런 표본에서 표준 \(F\)가 더 자주 틀린다. 선택 자체가 자료에 의존하므로 편향이 생긴다.

이것이 "사전검정의 역설"이다. 가정을 검정해서 방법을 고르는 절차는 두 방법 중 어느 것보다도 나쁠 수 있다.

절차 오류율의 성격
항상 \(F\) 가정이 맞으면 정확, 틀리면 재앙
항상 웰치 언제나 0.05 근처
2단계 두 절차의 나쁜 점을 섞음

이분산·균형에서는 2단계가 0.0497로 괜찮다. 레빈의 검정력이 0.94로 높아서다. 검정력이 높을 때만 2단계가 작동하는데, 그것을 미리 알 수 없다.

같은 논리가 다른 사전검정에도 적용된다.

사전검정 대신 할 일
레빈 → 웰치 분기 항상 웰치
샤피로 → 비모수 분기 사전에 정한 방법을 쓴다
정규성 → 변환 분기 자료를 보기 전에 변환을 정한다

본문의 작업 흐름을 고쳐야 한다. "레빈으로 확인하고 다르면 웰치로"가 아니라 "처음부터 웰치를 쓰고, 레빈은 자료를 이해하는 용도로만 본다"가 옳다.

레빈 검정이 쓸모없다는 말은 아니다. 분산이 왜 다른지 자료를 이해하는 데는 유용하다. 다만 방법 선택의 스위치로 쓰지 않는다.

연습문제 8. 본문은 "집단당 20–30개 미만이면 치우침이 오류율을 부풀리거나 줄일 수 있다"고 한다. 치우침의 정도와 \(n\)을 바꿔 가며 어느 쪽인지 확인하라.

풀이
import numpy as np
from scipy import stats

rng = np.random.default_rng(818)
B = 8_000
dists = {
    "정규 (치우침 0)": lambda n: rng.normal(0, 1, n),
    "지수 (치우침 2)": lambda n: rng.exponential(1, n) - 1,
    "카이제곱 1 (치우침 2.8)": lambda n: rng.chisquare(1, n) - 1,
    "로그정규 (치우침 6.2)": lambda n: np.exp(rng.normal(0, 1, n)) - np.exp(.5),
    "파레토 a=3 (치우침 ∞)": lambda n: (rng.pareto(3, n) + 1) - 1.5,
}
ns = [5, 10, 20, 50, 100]
print("k=3, 등분산·균형, 명목 0.05")
print(f"{'분포':>22s} " + " ".join(f"{'n=' + str(n):>8s}" for n in ns))
for lab, f in dists.items():
    row = [sum(stats.f_oneway(f(n), f(n), f(n)).pvalue < 0.05
               for _ in range(B)) / B for n in ns]
    print(f"{lab:>22s} " + " ".join(f"{r:8.4f}" for r in row))
k=3, 등분산·균형, 명목 0.05
                    분포      n=5     n=10     n=20     n=50    n=100
            정규 (치우침 0)   0.0522   0.0476   0.0469   0.0471   0.0535
            지수 (치우침 2)   0.0393   0.0429   0.0508   0.0480   0.0530
      카이제곱 1 (치우침 2.8)   0.0346   0.0334   0.0447   0.0454   0.0418
        로그정규 (치우침 6.2)   0.0314   0.0341   0.0385   0.0420   0.0446
       파레토 a=3 (치우침 ∞)   0.0301   0.0336   0.0357   0.0410   0.0401

균형 설계에서 치우침은 언제나 "줄이는" 쪽이다. 부풀리지 않는다.

치우침 \(n=5\) \(n=100\)
0 (정규) 0.052 0.054
2 (지수) 0.039 0.053
6.2 (로그정규) 0.031 0.045
\(\infty\) (파레토) 0.030 0.040

수렴이 매우 느리다. 로그정규는 \(n=100\)에서도 0.045로 명목에 못 미친다. 치우침 6.2를 씻어내려면 \(n\)이 수백 필요하다.

보수적인 것이 안전한가. 아니다. 오류율 0.03은 검정력을 잃었다는 뜻이다. 실제 차이가 있어도 덜 잡는다.

그런데 "부풀리는" 경우는 언제인가. 치우침 혼자서는 부풀리지 않는다. 불균형·이분산과 겹칠 때 생긴다.

rng = np.random.default_rng(8181)
B = 8_000
lg = lambda n: np.exp(rng.normal(0, 1, n)) - np.exp(.5)
print("로그정규 기저, 척도를 곱해 이분산을 만듦 (명목 0.05)")
print(f"{'설계':>32s} {'표준 F':>8s}")
for lab, ns, sc in [
    ("균형·등척도 n=(20,20,20)", [20, 20, 20], [1, 1, 1]),
    ("불균형 n=(40,20,8) 등척도", [40, 20, 8], [1, 1, 1]),
    ("역페어링 n=(40,20,8) 척도=(1,2,4)", [40, 20, 8], [1, 2, 4]),
    ("정페어링 n=(8,20,40) 척도=(1,2,4)", [8, 20, 40], [1, 2, 4]),
]:
    a = sum(stats.f_oneway(*[lg(n) * s for n, s in zip(ns, sc)]).pvalue < 0.05
            for _ in range(B))
    print(f"{lab:>32s} {a / B:8.4f}")
로그정규 기저, 척도를 곱해 이분산을 만듦 (명목 0.05)
                              설계     표준 F
             균형·등척도 n=(20,20,20)   0.0356
             불균형 n=(40,20,8) 등척도   0.0489
     역페어링 n=(40,20,8) 척도=(1,2,4)   0.3003
     정페어링 n=(8,20,40) 척도=(1,2,4)   0.0333

역페어링에서 0.3003이 된다. 치우침 자체가 아니라 치우침 + 이분산 + 불균형의 조합이 재앙이다.

조합 오류율
치우침만 0.036 (보수적)
치우침 + 불균형 0.049 (정상)
치우침 + 이분산 + 역페어링 0.300

불균형만으로는 문제가 없다(0.0489). 이분산이 반드시 끼어야 무너진다.

정리 — 본문을 이렇게 읽는다.

본문 서술 정확한 내용
치우침이 오류율을 줄인다 균형 설계에서 언제나 참
치우침이 오류율을 부풀린다 이분산·불균형과 겹칠 때만
\(n>30\)이면 괜찮다 치우침이 2 이하일 때만

실무 지침 셋.

  1. 균형 설계를 유지하면 치우침의 해가 보수성으로 끝난다.
  2. 치우침이 심하면 변환을 고려한다. 검정력을 되찾기 위해서다.
  3. 치우침 + 이분산이면 웰치만으로 부족하다(11장 웰치 절 참조). 변환이나 부트스트랩이 필요하다.

연습문제 9. 본문은 잔차로 정규성을 검정하라고 한다. 그런데 잔차는 관측값이 아니다. 이것이 샤피로 검정에 어떤 영향을 주는지, 그리고 \(n\)이 크면 왜 검정이 무의미해지는지 보여라.

풀이

문제 둘.

문제 내용
잔차는 독립이 아니다 집단마다 \(\sum_j e_{ij}=0\)
\(n\)이 크면 사소한 위반도 유의 검정력이 너무 좋아진다
import warnings
warnings.filterwarnings("ignore")

import numpy as np
from scipy import stats

rng = np.random.default_rng(919)
B = 6_000
print("(가) 자료가 정말 정규일 때 샤피로 검정의 기각률 (명목 0.05)")
print(f"{'집단당 n':>10s} {'참 오차에 적용':>14s} {'잔차에 적용':>12s}")
for n in [10, 20, 50]:
    a = b = 0
    for _ in range(B):
        gs = [rng.normal(0, 1, n) for _ in range(3)]
        eps = np.concatenate(gs)                          # 참 오차
        res = np.concatenate([g - g.mean() for g in gs])  # 잔차
        a += stats.shapiro(eps).pvalue < 0.05
        b += stats.shapiro(res).pvalue < 0.05
    print(f"{n:10d} {a / B:14.4f} {b / B:12.4f}")

print("\n(나) 약간만 치우친 분포(감마 shape=9, 치우침 0.67)에서")
print(f"{'집단당 n':>10s} {'샤피로 기각률':>13s} {'F 의 실제 오류율':>15s}")
for n in [10, 20, 50, 100, 200]:
    a = b = 0
    for _ in range(B // 2):
        gs = [rng.gamma(9, 1, n) - 9 for _ in range(3)]
        res = np.concatenate([g - g.mean() for g in gs])
        a += stats.shapiro(res).pvalue < 0.05
        b += stats.f_oneway(*gs).pvalue < 0.05
    print(f"{n:10d} {a / (B // 2):13.4f} {b / (B // 2):15.4f}")
(가) 자료가 정말 정규일 때 샤피로 검정의 기각률 (명목 0.05)
     집단당 n       참 오차에 적용       잔차에 적용
        10         0.0565       0.0495
        20         0.0503       0.0492
        50         0.0493       0.0493

(나) 약간만 치우친 분포(감마 shape=9, 치우침 0.67)에서
     집단당 n       샤피로 기각률      F 의 실제 오류율
        10        0.1867          0.0503
        20        0.3837          0.0470
        50        0.8233          0.0583
       100        0.9903          0.0533
       200        1.0000          0.0533

(가) 잔차 사용은 거의 해롭지 않다. 기각률이 0.049~0.050으로 명목을 지킨다. 집단별로 중심화하는 것만으로는 검정을 크게 왜곡하지 않는다.

다만 약간 보수적이다(\(n=10\)에서 0.0495 대 0.0565). 제약 \(\sum_j e_{ij}=0\)이 자유도를 하나씩 먹기 때문인데, 실무적으로 무시할 수준이다.

(나)가 진짜 문제다.

집단당 \(n\) 샤피로 기각률 \(F\)의 실제 오류율
10 0.187 0.050
50 0.823 0.058
100 0.990 0.053
200 1.000 0.053

\(n=200\)에서 샤피로는 100% 기각하지만 \(F\) 검정은 완벽하다(0.053).

정규성 검정은 "정규인가"를 묻지만, 우리가 알고 싶은 것은 "\(F\) 검정이 작동하는가"다. 이 둘은 다른 질문이다.

\[ \text{샤피로의 검정력}\uparrow\text{ (}n\text{ 증가)} \qquad\text{동시에}\qquad F\text{의 로버스트성}\uparrow\text{ (중심극한정리)} \]

\(n\)이 커지면 정규성 검정은 더 민감해지고 \(F\) 검정은 덜 민감해진다. 정확히 반대 방향이다.

그래서 어떻게 하나.

상황 권장
\(n\)이 작음(\(<20\)) 그림으로 본다(Q-Q). 검정은 검정력이 없다
\(n\)이 중간 그림 + 치우침·첨도 수치
\(n\)이 큼(\(>100\)) 검정을 무시한다. 중심극한정리가 작동

검정 대신 볼 것 셋.

  1. Q-Q 그림. 벗어남의 모양을 보여 준다(꼬리인지 중심인지).
  2. 치우침과 첨도. \(|{\rm skew}|>2\) 또는 초과첨도 \(>7\)이면 주의(Kline의 경험칙).
  3. 이상값. 한두 점이 문제라면 정규성이 아니라 그 점의 문제다.

본문의 작업 흐름 4단계를 고쳐 쓰면. "샤피로-윌크 검정으로 정규성을 확인한다"가 아니라 "Q-Q 그림으로 벗어남의 모양을 보고, 치우침 지표를 확인하며, \(n\)이 크면 검정 결과는 참고만 한다"가 정확하다.

연습문제 10. 네 가정을 위험도 순으로 정리하고, 각각의 진단과 처방을 표로 만들어라.

풀이

위험도 순위(균형 설계, \(n=15\) 기준).

순위 가정 위반 시 오류율 명목 대비
1 독립성 (\(\rho=0.6\)) 0.475 9.5배
2 등분산 + 불균형 0.286 5.7배
3 등분산 (균형) 0.072 1.4배
4 정규성 (균형) 0.037 0.7배(보수적)

순위가 상황에 의존한다. 등분산 위반은 균형이면 3위, 불균형이면 2위다.

가정별 진단과 처방.

가정 진단 처방 비고
독립성 설계 검토(반복측정? 군집? 시계열?) 혼합효과 모형, 군집 로버스트 사후 교정 불가
등분산 칸별 \(s_i^2\), 잔차 대 적합값 그림 웰치(기본), 변환 레빈은 참고용
정규성 Q-Q 그림, 치우침·첨도 변환, 순열검정, 큰 표본 검정은 \(n\)이 크면 무의미
선형성 부분잔차 그림 다항항, 스플라인, 변환 공변량이 있을 때만

작업 흐름(개정판).

0. 설계를 검토한다 ── 독립성은 여기서 끝난다
     │  (반복측정·군집이면 분산분석을 쓰지 않는다)
     ↓
1. 칸별 n, 평균, 표준편차를 본다
     │  불균형인가? 분산비는? 역페어링인가?
     ↓
2. 처음부터 웰치를 쓴다 ── 레빈으로 분기하지 않는다
     ↓
3. 잔차를 그림으로 본다 ── Q-Q, 잔차 대 적합값
     │  치우침이 심하면 변환이나 부트스트랩
     ↓
4. 공변량이 있으면 선형성 확인
     ↓
5. 보고: 방법의 선택 이유와 가정 점검 결과를 함께

본문과 달라진 점 셋.

본문 개정 이유
레빈으로 확인 후 분기 항상 웰치 사전검정의 역설(연습문제 7)
샤피로로 정규성 검정 그림 + 지표 \(n\)이 크면 무의미(연습문제 9)
독립성을 3번째로 0번째 가장 치명적이고 교정 불가(연습문제 6)

경험칙 넷.

  1. 균형 설계가 최고의 방어다. 이분산의 해를 1.4배로 묶는다.
  2. 분산비 4배 + 역페어링이면 표준 \(F\)를 쓰지 않는다.
  3. 치우침 2 이하 + \(n\geq20\)이면 정규성은 걱정하지 않는다.
  4. 가정 검정으로 방법을 고르지 않는다. 자료를 보기 전에 정한다.

한 문장. 가정은 검정해서 통과 여부를 가리는 관문이 아니라, 어떤 방법이 이 자료에 맞는지 판단하기 위한 정보다.


정리하며

분산분석의 타당성은 오차항에 부과되는 조건에 달려 있다.

가정 어긋나면 강건성
정규성 \(F\) 가 정확한 분포를 안 따름 대표본에서 강건
독립성 표준오차 과소, \(F\) 부풀림 강건하지 않음
등분산성 불균형과 겹치면 크게 왜곡 웰치로 해결 가능
선형성 모형이 구조를 놓침 —
  • 독립성이 가장 중요하다. 다른 셋은 변환·대안 검정·로버스트 방법으로 대처할 수 있지만, 독립성 위반은 모형 자체를 바꿔야 한다(혼합효과·반복측정).
  • 정규성은 잔차에 대한 가정이다. 원자료가 아니라 \(e_{ij}=Y_{ij}-\bar Y_{i\cdot}\) 를 본다.
  • 등분산 위반은 불균형과 만날 때 치명적이다. 둘 중 하나만 있으면 견딜 만하지만 겹치면 제1종 오류율이 크게 어긋난다.
  • 가정 확인은 검정이 아니라 진단이다. 형식적 검정은 표본크기에 좌우되므로 그림과 함께 보아야 한다.

이어지는 절들이 각 가정의 구체적인 진단 절차를 다룬다. 정규성 확인부터 시작한다.