대비 (Contrast) 의 일반화 — Complex Contrasts

임의의 합 0 계수 조합으로 그룹 평균을 비교

Maxwell Ch.4 의 대비 (contrast) 정의를 일반화한다. 합 0 제약을 가진 계수 조합으로 단순 비교 (1 vs 1), 복합 비교 (1 vs 평균), 추세 검정 (linear trend) 등 다양한 가설을 통합 표현한다. 대비 추정량의 분산, 표준 오차, t 통계량, 그리고 모형 비교와의 연결을 다룬다.

Experimentation
Fundamentals
저자

Kwangmin Kim

공개

2026년 05월 08일

1 도입 — 두 그룹 비교를 넘어서

A-MAX4-1 에서 두 그룹 평균 비교 (\(\mu_1 - \mu_2\)) 를 모형 비교로 도출했다. 이 글은 더 일반적 인 비교 — 한 그룹 vs 나머지, 두 그룹 vs 두 그룹, 선형 추세 등 — 로 확장한다. 이 일반화의 도구가 대비 (contrast) 이다.

정의: 대비 (Contrast)

그룹 평균 \(\mu_1, \mu_2, \ldots, \mu_J\)선형 결합 으로, 계수 합이 0 인 것:

\[ \psi = \sum_{j=1}^{J} c_j \mu_j, \quad \sum_{j=1}^{J} c_j = 0 \]

  • \(c_j\): 대비 계수 (실수)
  • 합 0 제약은 대비가 평균 차이만 측정 하도록 보장

2 흔한 대비 패턴

2.1 패턴 1 — 단순 비교 (Simple Contrast)

두 그룹 비교: \(c = (1, -1, 0, 0)\).

\[ \psi = \mu_1 - \mu_2 \]

A-MAX4-1 의 사례.

2.2 패턴 2 — 한 그룹 vs 나머지

그룹 1 을 나머지 3 그룹 평균과 비교: \(c = (1, -1/3, -1/3, -1/3)\).

\[ \psi = \mu_1 - \frac{\mu_2 + \mu_3 + \mu_4}{3} \]

이는 위약 (그룹 1) vs 활성 처치들의 평균 같은 가설에 적합하다.

2.3 패턴 3 — 두 그룹 vs 두 그룹

그룹 1, 2 의 평균과 그룹 3, 4 의 평균 비교: \(c = (1/2, 1/2, -1/2, -1/2)\).

\[ \psi = \frac{\mu_1 + \mu_2}{2} - \frac{\mu_3 + \mu_4}{2} \]

이는 2 × 2 요인 설계의 main effect 에 해당한다.

2.4 패턴 4 — 선형 추세 (Linear Trend)

수준이 순서 있는 (예: 약물 용량 0, 10, 20, 30 mg, 그룹 평균이 4 개) 경우:

\(c = (-3, -1, 1, 3)\) (또는 직교 다항 계수).

\[ \psi = -3\mu_1 - \mu_2 + \mu_3 + 3\mu_4 \]

이는 그룹 평균이 선형으로 증가/감소하는가 를 검정한다.

2.5 패턴 5 — 이차 추세 (Quadratic Trend)

같은 4 그룹에서 U 자 또는 역 U 자 형태 검정: \(c = (1, -1, -1, 1)\).

\[ \psi = \mu_1 - \mu_2 - \mu_3 + \mu_4 \]

직관 — 대비 계수 설계의 직관

대비 계수 \(c_j\)그 그룹이 비교에 기여하는 부호와 가중치 를 의미한다.

  • 계수가 같은 그룹들은 함께 합쳐져 한 쪽 평균을 형성한다.
  • 부호가 다른 그룹들은 비교의 양쪽 에 위치한다.
  • 계수의 절댓값이 가중치 를 정한다.

A/B 테스트에서 4 변형 (대조군, 신규 A, 신규 B, 신규 C) 을 실행한다고 하자. 다음 비교들이 가능하다.

가설 대비 계수
“신규 변형들이 대조군보다 나은가?” \((1, -1/3, -1/3, -1/3)\)
“신규 A 가 신규 B 보다 나은가?” \((0, 1, -1, 0)\)
“신규 A, B 의 평균이 대조군 + 신규 C 의 평균보다 나은가?” \((-1/2, 1/2, 1/2, -1/2)\)

같은 자료에 대해 다른 가설 을 검정하기 위해 다른 대비 를 사용한다. 비즈니스 질문이 결정한다.

3 대비 추정량의 분산

대비 \(\psi = \sum c_j \mu_j\) 의 표본 추정량:

\[ \widehat{\psi} = \sum_{j=1}^{J} c_j \bar{Y}_j \]

\(\bar{Y}_j\) 의 분산은 \(\sigma^2 / n_j\) 이고, 그룹들이 독립 이므로 (독립 변량의 선형 결합):

\[ \text{Var}(\widehat{\psi}) = \sum_{j=1}^{J} c_j^2 \cdot \text{Var}(\bar{Y}_j) = \sigma^2 \sum_{j=1}^{J} \frac{c_j^2}{n_j} \]

3.1 표준 오차

\(\sigma^2\)\(\text{MS}_W\) 로 추정:

\[ \text{SE}(\widehat{\psi}) = \sqrt{\text{MS}_W \sum_{j=1}^{J} \frac{c_j^2}{n_j}} \]

균형 설계 (\(n_j = n_0\)) 에서:

\[ \text{SE}(\widehat{\psi}) = \sqrt{\frac{\text{MS}_W}{n_0} \sum_{j=1}^{J} c_j^2} \]

4 대비의 t 통계량과 F 통계량

t 통계량:

\[ t = \frac{\widehat{\psi}}{\text{SE}(\widehat{\psi})} = \frac{\sum c_j \bar{Y}_j}{\sqrt{\text{MS}_W \sum c_j^2 / n_j}} \]

자유도 \(n - J\) (전체 ANOVA 의 잔차 자유도).

F 통계량:

\[ F = t^2 = \frac{(\sum c_j \bar{Y}_j)^2}{\text{MS}_W \sum c_j^2 / n_j} \]

자유도 \(F_{1, n-J}\).

5 대비의 SS

대비의 제곱합 (Sum of Squares for Contrast):

\[ \text{SS}_{\psi} = \frac{(\widehat{\psi})^2}{\sum c_j^2 / n_j} = \frac{(\sum c_j \bar{Y}_j)^2}{\sum c_j^2 / n_j} \]

이는 그 대비가 설명하는 분산 이다. F 통계량은 \(\text{SS}_{\psi} / \text{MS}_W\) 와 같다.

직관 — \(\text{SS}_{\psi}\) 의 의미

대비의 제곱합은 “이 비교가 자료의 어느 부분을 설명하는가” 를 정량화한다. 옴니버스 ANOVA 의 \(\text{SS}_B\)모든 그룹 차이의 합 이지만, \(\text{SS}_{\psi}\)특정 비교만 의 부분이다.

따라서 \(\text{SS}_{\psi} \leq \text{SS}_B\) 이고, \(\text{SS}_{\psi} = \text{SS}_B\) 일 때는 그 대비가 모든 그룹 차이를 완전히 포착한 경우다 (예: 그룹이 정확히 두 종류인데 한 대비로 그 차이를 잡은 경우).

여러 직교 대비를 사용하면 \(\text{SS}_B = \sum_k \text{SS}_{\psi_k}\) 로 분해된다 (다음 글 A-MAX4-3 의 주제).

6 모형 비교 관점에서의 대비 검정

대비 검정도 모형 비교 로 표현된다. Full model 은 ANOVA 와 동일.

\[ \text{Full: } Y_{ij} = \mu_j + \varepsilon_{ij} \]

Restricted model 은 대비 = 0 의 제약을 추가한다.

\[ H_0: \psi = \sum c_j \mu_j = 0 \]

이 제약은 그룹 평균들 사이에 한 개의 선형 관계 를 부과한다. 따라서 모수의 자유로움이 1 줄어든다.

6.1 자유도

  • Full model: \(J\) 개 모수
  • Restricted model: \(J - 1\) 개 모수 (한 개의 제약)
  • 자유도 차이: 1

이것이 모든 대비 검정의 분자 자유도가 1 인 이유다.

7 대비의 신뢰 구간

\(\widehat{\psi}\) 의 95 % 신뢰 구간:

\[ \widehat{\psi} \pm t_{0.025, n-J} \cdot \text{SE}(\widehat{\psi}) \]

이 CI 가 효과 크기 보고 의 핵심이다.

7.1 두 그룹 비교 사례

A-MAX4-1 의 두 그룹 비교 (\(c = (1, -1, 0, \ldots)\)) 의 CI:

\[ (\bar{Y}_1 - \bar{Y}_2) \pm t_{0.025, n-J} \cdot \sqrt{\text{MS}_W \left(\frac{1}{n_1} + \frac{1}{n_2}\right)} \]

이는 두 평균 차이의 신뢰 구간 이다. 비즈니스 의사결정에 직접 사용된다.

8 대비 설계 — 가설 → 계수

연구 가설을 대비 계수로 변환하는 절차.

8.1 단계 1 — 가설을 단어로 표현

예: “신약 (그룹 1) 이 위약 (그룹 4) 과 두 다른 활성 약물 (그룹 2, 3) 의 평균보다 우수한가?”

8.2 단계 2 — 계수의 부호 결정

  • 그룹 1 (신약) → 양수 (가설이 우수 이므로)
  • 그룹 4 (위약) → 음수
  • 그룹 2, 3 (활성 약물) → 음수

8.3 단계 3 — 가중치 결정

  • 그룹 1 vs (그룹 2, 3, 4 의 평균) 비교라면 3 그룹의 평균 이 한쪽
  • 계수: \((1, -1/3, -1/3, -1/3)\) — 합 0 OK

또는 다른 형태:

  • 그룹 1 vs 그룹 4 만 비교 (그룹 2, 3 은 무관)
  • 계수: \((1, 0, 0, -1)\) — 합 0 OK

가설의 정확한 형태 가 계수를 결정한다.

8.4 단계 4 — 직교성 점검 (선택)

여러 대비를 동시에 사용한다면, 서로 직교 인지 점검한다 (다음 글 A-MAX4-3 에서 다룸).

9 코드 예시 — 일반 대비 검정

import numpy as np
import pandas as pd
from scipy.stats import t as t_dist
import statsmodels.api as sm
from statsmodels.formula.api import ols

np.random.seed(42)
n_each = 20

# 4 그룹 자료
group_drug = np.random.normal(120, 10, n_each)        # 그룹 1
group_biofeedback = np.random.normal(125, 10, n_each)  # 그룹 2
group_diet = np.random.normal(123, 10, n_each)         # 그룹 3
group_combined = np.random.normal(115, 10, n_each)     # 그룹 4

groups = ['drug']*n_each + ['biofeedback']*n_each + ['diet']*n_each + ['combined']*n_each
all_data = np.concatenate([group_drug, group_biofeedback, group_diet, group_combined])
df = pd.DataFrame({'bp': all_data, 'treatment': groups})

# 옴니버스 ANOVA
model = ols('bp ~ C(treatment)', data=df).fit()
anova_table = sm.stats.anova_lm(model)
ms_w = anova_table['mean_sq'].iloc[1]
df_w = int(anova_table['df'].iloc[1])

# 그룹 평균과 표본 크기
group_order = ['drug', 'biofeedback', 'diet', 'combined']
means = np.array([df[df['treatment']==g]['bp'].mean() for g in group_order])
n_j = np.array([n_each] * 4)

def contrast_test(c, label):
    """대비 검정 함수"""
    psi_hat = (c * means).sum()
    se_psi = np.sqrt(ms_w * (c**2 / n_j).sum())
    t_stat = psi_hat / se_psi
    p_value = 2 * (1 - t_dist.cdf(abs(t_stat), df_w))
    ci_low = psi_hat - t_dist.ppf(0.975, df_w) * se_psi
    ci_high = psi_hat + t_dist.ppf(0.975, df_w) * se_psi
    ss_psi = psi_hat**2 / (c**2 / n_j).sum()
    print(f"\n[{label}] 계수 c = {c}")
    print(f"  ψ̂ = {psi_hat:.3f}, SE = {se_psi:.3f}")
    print(f"  t = {t_stat:.3f}, df = {df_w}, p = {p_value:.4f}")
    print(f"  95 % CI = ({ci_low:.3f}, {ci_high:.3f})")
    print(f"  SS_ψ = {ss_psi:.3f}")

# 대비 1: drug vs biofeedback
c1 = np.array([1, -1, 0, 0])
contrast_test(c1, "drug vs biofeedback")

# 대비 2: combined vs others avg
c2 = np.array([-1/3, -1/3, -1/3, 1])
contrast_test(c2, "combined vs others avg")

# 대비 3: behavioral (biofeedback + diet) vs medical (drug + combined)
c3 = np.array([-1/2, 1/2, 1/2, -1/2])
contrast_test(c3, "behavioral vs medical")

# 대비 4: linear trend (그룹이 순서를 가질 때)
c4 = np.array([-3, -1, 1, 3])  # 가상의 순서
contrast_test(c4, "linear trend")

이 코드는 4 가지 다른 대비 를 동일 자료에 적용한다. 각 대비의 효과 크기, p 값, CI 가 어떻게 다른지 비교할 수 있다.

10 대비의 한계 — 다중 비교 인플레이션

여러 대비를 동시에 검정하면 \(\alpha\) 인플레이션 이 일어난다. 예: 6 개의 대비 검정 (4 그룹의 모든 쌍별 비교) 에서 각 검정에 \(\alpha = 0.05\) 를 적용하면, 적어도 한 개의 거짓 양성 확률은:

\[ 1 - (1 - 0.05)^6 \approx 0.265 \]

즉 진짜 효과가 없어도 약 27 % 확률로 한 개의 검정이 유의해진다. 이것이 다중 비교 문제 이다.

해법:

  1. 사전 등록 + 직교 대비 — 가설 수가 적고 직교라면 보정 단순
  2. Bonferroni 보정 — 각 검정에 \(\alpha / k\) 를 사용 (\(k\) = 검정 수)
  3. Tukey HSD, Scheffé — 사후 모든 쌍 비교에 특화
  4. FDR (False Discovery Rate) — 거짓 양성 비율 통제

자세한 내용은 후속 시리즈 A-MAX5-* 에서 다룬다.

11 Trend Analysis — 추세 검정

수준이 순서 또는 양적 인 경우, 특별한 대비가 추세 분석 (Trend Analysis) 이다.

정의: Polynomial Contrasts

수준이 동일 간격이고 그룹이 \(J\) 개일 때, 직교 다항 대비 를 사용한다.

\(J\) Linear Quadratic Cubic Quartic
3 \((-1, 0, 1)\) \((1, -2, 1)\)
4 \((-3, -1, 1, 3)\) \((1, -1, -1, 1)\) \((-1, 3, -3, 1)\)
5 \((-2, -1, 0, 1, 2)\) \((2, -1, -2, -1, 2)\) \((-1, 2, 0, -2, 1)\) \((1, -4, 6, -4, 1)\)

이 계수들은 서로 직교 이며 \(\text{SS}_B\) 를 완전 분해한다.

11.1 사용 시점

  • 약물 용량 (0, 10, 20, 30 mg) 의 효과
  • 학습 시간 (1, 2, 3, 4 시간) 의 영향
  • 온도 (10, 20, 30, 40 ℃) 의 반응

11.2 해석

  • Linear 유의 → 단조 증가/감소 추세
  • Quadratic 유의 → U 자 또는 역 U 자 (최댓값 또는 최솟값)
  • 더 고차 → 복잡한 패턴

추세 분석은 Maxwell Ch.6 의 주요 주제이며, 양적 요인 (quantitative factor) 에 특화되어 있다.

12 Contrast 의 자세한 도출

12.1 검정 통계량의 일반 형태

대비 \(\psi = \sum c_j \mu_j\) 의 t 통계량 도출:

정의: Contrast t-statistic

추정량의 분산:

\[ \text{Var}(\widehat{\psi}) = \text{Var}\left(\sum c_j \bar{Y}_j\right) = \sum c_j^2 \cdot \text{Var}(\bar{Y}_j) = \sigma^2 \sum \frac{c_j^2}{n_j} \]

t 통계량:

\[ t = \frac{\widehat{\psi}}{\sqrt{\text{MS}_W \cdot \sum c_j^2/n_j}} \]

자유도: \(n - J\) (전체 ANOVA 잔차).

12.2 F 통계량과의 동등성

\(F = t^2 \sim F_{1, n-J}\). 두 검정 동등.

12.3 사례 — 4 가지 약물 비교

import numpy as np
from scipy.stats import t as t_dist
import statsmodels.api as sm
from statsmodels.formula.api import ols
import pandas as pd

np.random.seed(42)
n_per = 25

# 4 그룹 (위약, 약물 A, B, C)
groups = {
    'Placebo': np.random.normal(120, 12, n_per),
    'Drug_A': np.random.normal(115, 12, n_per),
    'Drug_B': np.random.normal(110, 12, n_per),
    'Drug_C': np.random.normal(108, 12, n_per),
}

# 자료 합치기
df_list = []
for name, data in groups.items():
    for val in data:
        df_list.append({'group': name, 'bp': val})
df = pd.DataFrame(df_list)

# ANOVA
model = ols('bp ~ C(group)', data=df).fit()
ms_w = sm.stats.anova_lm(model)['mean_sq'].iloc[1]
df_w = int(sm.stats.anova_lm(model)['df'].iloc[1])

# 그룹 평균
means = df.groupby('group')['bp'].mean()
print("그룹 평균:")
print(means)

# 다양한 대비
contrasts = {
    'Placebo vs Avg(Drugs)': {'Placebo': 1, 'Drug_A': -1/3, 'Drug_B': -1/3, 'Drug_C': -1/3},
    'Drug_A vs Drug_B': {'Placebo': 0, 'Drug_A': 1, 'Drug_B': -1, 'Drug_C': 0},
    'Linear trend (가상 용량)': {'Placebo': -3, 'Drug_A': -1, 'Drug_B': 1, 'Drug_C': 3},
    'Quadratic trend': {'Placebo': 1, 'Drug_A': -1, 'Drug_B': -1, 'Drug_C': 1},
}

for name, c in contrasts.items():
    psi = sum(c[g] * means[g] for g in c)
    se = np.sqrt(ms_w * sum(c[g]**2 / n_per for g in c))
    t_stat = psi / se
    p_val = 2 * (1 - t_dist.cdf(abs(t_stat), df_w))
    ci_lower = psi - t_dist.ppf(0.975, df_w) * se
    ci_upper = psi + t_dist.ppf(0.975, df_w) * se
    print(f"\n[{name}]")
    print(f"  ψ = {psi:.3f}, SE = {se:.3f}")
    print(f"  t = {t_stat:.3f}, p = {p_val:.4f}")
    print(f"  95 % CI = ({ci_lower:.3f}, {ci_upper:.3f})")

이 코드가 4 가지 다른 대비 의 동시 분석.

13 Polynomial Contrasts 의 자세한 표

13.1 등 간격 수준의 직교 다항

수준이 동일 간격 인 경우의 직교 다항 계수:

\(J\) Linear Quadratic Cubic Quartic
3 (-1, 0, 1) (1, -2, 1)
4 (-3, -1, 1, 3) (1, -1, -1, 1) (-1, 3, -3, 1)
5 (-2, -1, 0, 1, 2) (2, -1, -2, -1, 2) (-1, 2, 0, -2, 1) (1, -4, 6, -4, 1)
6 (-5, -3, -1, 1, 3, 5) (5, -1, -4, -4, -1, 5)

이 계수들이 서로 직교 이며 SS 분해 가능.

13.2 Spaced Levels (불등 간격)

수준이 불등 간격 (예: 0, 5, 20, 100 mg) 이면 수정 다항 계수 필요. R contr.poly() 자동 생성.

14 A/B 테스트의 Contrast Examples

14.1 시나리오 — 4 변형 비교

# 4 변형 + 다양한 비교
variants = {
    'Control': 0.05,    # 대조군
    'Variant_A': 0.052,  # 약간 향상
    'Variant_B': 0.058,  # 중간 향상
    'Variant_C': 0.070,  # 큰 향상
}

# 비즈니스 가설별 대비
contrasts_ab = {
    '대조 vs 모든 신규': {'Control': 1, 'Variant_A': -1/3, 'Variant_B': -1/3, 'Variant_C': -1/3},
    '소규모 (A) vs 대규모 (B+C)': {'Control': 0, 'Variant_A': 2, 'Variant_B': -1, 'Variant_C': -1},
    '점진 vs 혁신 (Linear)': {'Control': -3, 'Variant_A': -1, 'Variant_B': 1, 'Variant_C': 3},
}

# 각 대비의 비즈니스 의미 명확히
print("각 대비의 비즈니스 가설:")
for name, c in contrasts_ab.items():
    psi = sum(c[v] * variants[v] for v in c)
    print(f"  [{name}]")
    print(f"    계수: {c}")
    print(f"    ψ = {psi:.4f}")

각 대비가 다른 비즈니스 질문 에 답.

15 Contrast 의 수학적 직교성 - 추가

15.1 직교 조건의 유도

두 대비 \(\psi_1 = \sum c_{1j} \mu_j\), \(\psi_2 = \sum c_{2j} \mu_j\).

추정량의 공분산:

\[ \text{Cov}(\widehat{\psi}_1, \widehat{\psi}_2) = \sum_j c_{1j} c_{2j} \cdot \text{Cov}(\bar{Y}_j, \bar{Y}_j) = \sigma^2 \sum_j \frac{c_{1j} c_{2j}}{n_j} \]

(다른 그룹은 독립).

직교 (공분산 0):

\[ \sum_j \frac{c_{1j} c_{2j}}{n_j} = 0 \]

균형 설계: \(\sum c_{1j} c_{2j} = 0\).

수학적 정의통계적 독립성 보장.

16 후속 — 직교 대비와 효과 크기

다음 글 A-MAX4-3 은 직교 대비의 SS 가산성대비의 효과 크기 측정 을 다룬다.

17 관련 주제

선행 지식

후속 주제 (Phase A)

다른 카테고리 연결

Subscribe

Enjoy this blog? Get notified of new posts by email: