1 \(a \times b\) Within 의 효과 차원
피험자 \(i = 1, \ldots, n\) 가 \(a \times b\) 모든 셀에서 측정. 셀 평균 \(Y_{ijk}\) (\(j = 1, \ldots, a\); \(k = 1, \ldots, b\)).
세 효과의 차원:
| 효과 | 자유도 | D 차원 | 검정 |
|---|---|---|---|
| \(A\) main | \(a-1\) | \(a-1\) | one-sample \(T^2\) |
| \(B\) main | \(b-1\) | \(b-1\) | one-sample \(T^2\) |
| \(A \times B\) | \((a-1)(b-1)\) | \((a-1)(b-1)\) | one-sample \(T^2\) |
자유도 1 효과 (\(a=2\) 또는 \(b=2\)) 는 paired \(t\)-test.
2 D variable 의 일반 구성
2.1 \(A\) main (across \(B\) 평균)
각 피험자 \(i\) 에 대해: \[ \bar Y^{(A)}_{ij} = \frac{1}{b} \sum_{k=1}^{b} Y_{ijk}, \quad j = 1, \ldots, a \]
D variable (직교 contrast 적용 가능): \[ D^{(A)}_{ij} = \sum_{j' = 1}^a c_{j'}^{(j)} \bar Y^{(A)}_{ij'}, \quad j = 1, \ldots, a-1 \]
2.2 \(B\) main
비슷하게 across \(A\) 평균: \[ \bar Y^{(B)}_{ik} = \frac{1}{a} \sum_{j=1}^a Y_{ijk} \] \[ D^{(B)}_{ik} = \sum_{k'} c_{k'}^{(k)} \bar Y^{(B)}_{ik'}, \quad k = 1, \ldots, b-1 \]
2.3 \(A \times B\) 의 D variable
직교 contrast 의 곱 (Kronecker product): \[ D^{(AB)}_{i, jk} = \sum_{j', k'} c_{j'}^{(j)} c_{k'}^{(k)} Y_{i, j', k'} \]
\((a-1)(b-1)\) 차원.
3 \(3 \times 4\) 사례
\(A\) = 3 약 종류 (A, B, C), \(B\) = 4 시점 (1, 2, 4, 8 시간 후), \(n = 18\).
3.1 차원
| 효과 | \(df\) | D 차원 |
|---|---|---|
| \(A\) main | 2 | 2 |
| \(B\) main | 3 | 3 |
| \(A \times B\) | 6 | 6 |
3.2 검정의 자유도
각 효과의 Hotelling \(T^2\) 의 \(F\) 분포:
- \(A\): \(F(p, n-p) = F(2, 16)\).
- \(B\): \(F(p, n-p) = F(3, 15)\).
- \(A \times B\): \(F(p, n-p) = F(6, 12)\).
3.3 검정력 점검 — \(A \times B\) 의 검정력 약
자유도 \((6, 12)\) 의 \(F\) 검정 — 분모 자유도 12 작음. 효과 크기 보통 (\(f^2 \approx 0.1\)) 에서 검정력 ≈ 60%. 권장 표본:
| 차원 | 권장 \(n\) | 추가 점 |
|---|---|---|
| 1 | 10 | paired \(t\) 충분 |
| 2 | 15 | \(T^2\) 권장 |
| 3 | 20 | 분모 ≥ 17 |
| 6 | 25 | 분모 ≥ 19 |
| 9 | 30+ | 더 큰 표본 |
multivariate within 은 차원에 따라 표본 요구 ↑.
4 직교 다항식 기반 trend 분해
\(B\) 가 양적 (시점) 이면 D variable 을 직교 다항식으로 구성:
4.1 \(B\) main 의 trend 분해
\(B\) levels 양적 (1, 2, 4, 8 시간) — 등간격 아님. 직교 다항식 재계산 (G-MAX6-3) 필요.
또는 로그 변환 후 등간격 (\(\log_2 = 0, 1, 2, 3\)) → 표준 직교 다항식 사용:
선형: \((-3, -1, +1, +3)\). 이차: \((+1, -1, -1, +1)\). 삼차: \((-1, +3, -3, +1)\).
각 D variable: \[ D^{(B, \text{lin})}_i = \sum_k c_k^{\text{lin}} \bar Y^{(B)}_{ik} \] \[ D^{(B, \text{quad})}_i = \sum_k c_k^{\text{quad}} \bar Y^{(B)}_{ik} \] \[ D^{(B, \text{cub})}_i = \sum_k c_k^{\text{cub}} \bar Y^{(B)}_{ik} \]
각 차원이 독립적 의미 — 선형 trend, 이차 trend, 삼차 trend.
4.2 \(A \times B\) 의 trend 분해
\(A\) contrast × \(B\) trend contrast = 6 개 1 자유도 대비:
- \(A_1 \times B_{\text{lin}}\)
- \(A_1 \times B_{\text{quad}}\)
- \(A_1 \times B_{\text{cub}}\)
- \(A_2 \times B_{\text{lin}}\)
- \(A_2 \times B_{\text{quad}}\)
- \(A_2 \times B_{\text{cub}}\)
여기서 \(A_1, A_2\) 는 \(A\) 의 두 직교 contrast (예: A vs B+C, B vs C).
각 1 자유도가 의미 있는 가설: - “\(A\) 의 첫 contrast 에서 \(B\) 의 선형 추세가 다른가?” → \(A_1 \times B_{\text{lin}}\). - “\(A\) 의 둘째 contrast 에서 \(B\) 의 이차 추세가 다른가?” → \(A_2 \times B_{\text{quad}}\).
5 Multivariate 통합 + Univariate 분해
multivariate \(T^2\) 는 omnibus — 효과가 어느 차원에서 오는지 모름.
omnibus 유의 → 각 차원의 univariate \(t\)-test 로 follow-up.
직교 다항식 사용 시 각 차원이 독립적 의미 (선형, 이차, …) — 해석 명확.
명목 contrast 사용 시 각 차원이 dose comparison (예: dose 1 vs dose 2 평균).
5.1 Bonferroni 보정
차원별 검정 시 FWER 보정:
\[ \alpha_{\text{corrected}} = \alpha / p \]
\(p\) = D 차원.
Bonferroni 가 보수적. Holm-Bonferroni 또는 step-down 더 강력.
5.2 Closed Testing Procedure
- omnibus \(T^2\) 가 유의해야 차원별 검정 진행.
- 각 차원의 univariate \(t\) 의 \(p\) 값을 보정.
이는 Bonferroni 보다 검정력 ↑ — strong control of FWER.
6 가설 데이터 분석
6.1 약물 dose 별 시간 trajectory
요인: - \(A\) = 약 (placebo, drug A, drug B), 3 levels. - \(B\) = 시점 (1, 2, 4, 8 시간 후), 4 levels (로그 등간격).
피험자: \(n = 18\) 환자, 각 환자 모든 12 cell 측정.
6.2 가상 셀 평균
| 1h | 2h | 4h | 8h | |
|---|---|---|---|---|
| Placebo | 80 | 78 | 75 | 70 |
| Drug A | 82 | 75 | 65 | 50 |
| Drug B | 81 | 78 | 70 | 60 |
해석 (visual): - Placebo: 시간 ↑ → 약간 ↓ (자연 회복). - Drug A: 시간 ↑ → 강한 ↓ (강한 효과). - Drug B: 시간 ↑ → 중간 ↓.
6.3 A main 의 multivariate
\(A\) levels 별 평균 응답 (across \(B\)):
- Placebo: \((80+78+75+70)/4 = 75.75\)
- Drug A: \((82+75+65+50)/4 = 68\)
- Drug B: \((81+78+70+60)/4 = 72.25\)
D variable (Helmert contrast 가정): \[ D_1^{(A)} = \text{Drug A} - \text{Placebo} = -7.75 \] \[ D_2^{(A)} = \text{Drug B} - \text{Placebo} = -3.5 \]
Hotelling \(T^2\) on \(\bar{\mathbf{D}}^{(A)} = (-7.75, -3.5)\) — 2 차원.
6.4 B main 의 trend
\(\log_2 d \in \{0, 1, 2, 3\}\) 등간격. 표준 직교 다항식.
각 시점의 평균 응답 (across \(A\)):
- 1h: \((80+82+81)/3 = 81\)
- 2h: \(77\)
- 4h: \(70\)
- 8h: \(60\)
D variables: - \(D^{B,\text{lin}}\): \(-3(81) - 1(77) + 1(70) + 3(60) = -243 - 77 + 70 + 180 = -70\). - \(D^{B,\text{quad}}\): \(1(81) - 1(77) - 1(70) + 1(60) = -6\). - \(D^{B,\text{cub}}\): \(-1(81) + 3(77) - 3(70) + 1(60) = -81 + 231 - 210 + 60 = 0\).
해석: 강한 선형 감소, 약한 이차 (ceiling 효과 약), 삼차 0.
각 차원의 univariate \(t\) 검정: - linear \(t \approx -10\): 매우 유의. - quadratic \(t \approx -1\): 비유의. - cubic \(t \approx 0\): 비유의.
6.5 A × B 의 trend 분해
\(A_1\) (Drug A vs Placebo), \(A_2\) (Drug B vs Placebo), \(B\) trend 와 곱:
| Contrast | 의미 |
|---|---|
| \(A_1 \times B_{\text{lin}}\) | Drug A 의 선형 감소가 Placebo 와 다른가? |
| \(A_2 \times B_{\text{lin}}\) | Drug B 의 선형 감소가 Placebo 와 다른가? |
| \(A_1 \times B_{\text{quad}}\) | Drug A 의 이차 추세가 Placebo 와 다른가? |
| … | … |
Drug A 가 가장 강한 선형 감소 → \(A_1 \times B_{\text{lin}}\) 강하게 유의.
7 Python 코드 — 일반 \(a \times b\)
import numpy as np
import pandas as pd
from scipy import stats
np.random.seed(2026)
n = 18
A_levels = ["Placebo", "DrugA", "DrugB"]
B_levels = [1, 2, 4, 8] # 시간 (hours)
log2_B = [0, 1, 2, 3] # log2 등간격
cell_means = {
("Placebo", 1): 80, ("Placebo", 2): 78, ("Placebo", 4): 75, ("Placebo", 8): 70,
("DrugA", 1): 82, ("DrugA", 2): 75, ("DrugA", 4): 65, ("DrugA", 8): 50,
("DrugB", 1): 81, ("DrugB", 2): 78, ("DrugB", 4): 70, ("DrugB", 8): 60,
}
records = []
for subj in range(n):
pi = np.random.normal(0, 5)
for a in A_levels:
for b in B_levels:
y = cell_means[(a, b)] + pi + np.random.normal(0, 2)
records.append({"subject": subj, "A": a, "B": b, "Y": y})
data = pd.DataFrame(records)
# A main (across B 평균)
A_means = data.groupby(["subject", "A"])["Y"].mean().unstack()
D_A = pd.DataFrame({
"DrugA-Placebo": A_means["DrugA"] - A_means["Placebo"],
"DrugB-Placebo": A_means["DrugB"] - A_means["Placebo"],
})
D_bar_A = D_A.mean().values
S_D_A = D_A.cov().values
T2_A = n * D_bar_A @ np.linalg.inv(S_D_A) @ D_bar_A
F_A = (n - 2) / (2 * (n - 1)) * T2_A
p_A = 1 - stats.f.cdf(F_A, 2, n - 2)
print(f"=== A main ===")
print(f" D̄ = {D_bar_A}")
print(f" T² = {T2_A:.2f}, F({2}, {n-2}) = {F_A:.2f}, p = {p_A:.4f}")
# B main with orthogonal polynomial contrasts (log_2 등간격)
B_means = data.groupby(["subject", "B"])["Y"].mean().unstack()
c_lin = np.array([-3, -1, 1, 3]) / np.sqrt(20)
c_quad = np.array([1, -1, -1, 1]) / 2
c_cub = np.array([-1, 3, -3, 1]) / np.sqrt(20)
D_B = pd.DataFrame({
"B_lin": B_means.values @ c_lin,
"B_quad": B_means.values @ c_quad,
"B_cub": B_means.values @ c_cub,
})
D_bar_B = D_B.mean().values
S_D_B = D_B.cov().values
T2_B = n * D_bar_B @ np.linalg.inv(S_D_B) @ D_bar_B
F_B = (n - 3) / (3 * (n - 1)) * T2_B
p_B = 1 - stats.f.cdf(F_B, 3, n - 3)
print(f"\n=== B main (linear/quadratic/cubic) ===")
print(f" D̄ = {D_bar_B}")
print(f" T² = {T2_B:.2f}, F = {F_B:.2f}, p = {p_B:.4f}")
# 차원별 univariate t-test
print("\n=== B trend 차원별 검정 ===")
for col in D_B.columns:
t, p = stats.ttest_1samp(D_B[col], 0)
bon_p = min(1, p * 3)
print(f" {col}: t = {t:.2f}, raw p = {p:.4f}, Bonferroni p = {bon_p:.4f}")
# A × B interaction (단순화)
# 각 피험자에 대해 12 차원 vector → 직교 contrast 곱으로 6 차원 D
# (구현 복잡 — statsmodels 의 MANOVA 활용 권장)
from statsmodels.multivariate.manova import MANOVA
wide = data.pivot_table(index="subject", columns=["A", "B"], values="Y").reset_index()
# MANOVA 형식으로 long → wide 변환 후 fit8 가정과 한계
8.1 Multivariate 정규성
각 D variable 의 다변량 정규.
검정: Mardia’s test, Henze-Zirkler. 큰 \(n\) 에서 robust.
8.2 표본 충분
$n > $ 가장 큰 D 차원. 권장 $n $ 차원.
8.3 Sphericity 회피의 trade-off
multivariate 는 sphericity 가정 없지만 자유도 손실. 작은 \(n\) 에서는 univariate + ε 조정이 검정력 ↑.
8.4 결측 데이터
multivariate 는 listwise. 한 cell 결측이면 그 피험자 전체 제거.
대안: multilevel model (REML) 로 결측 자동 처리.
9 Multilevel 과의 통합
균등 완전 데이터에서 두 framework 가 동일 결과:
- Multivariate (D variable + Hotelling \(T^2\)): UN covariance 가정.
- Multilevel (mixed model with UN R structure): 동일 가정.
차이: - Multivariate: 명시적 vector 표현. 결측 시 listwise. - Multilevel: long format, 결측 자동 처리.
실무 권장: multilevel (R lme4, Python mixedlm) — 결측 우위, 비균등 데이터에 강. 정통 DOE textbook 의 multivariate 는 균등 데이터에 simple.
10 응용 — 실무 사례
10.1 1. 임상 longitudinal RCT
처치 (between, \(A\)) × 시점 (within, \(B\)). 시점이 양적이면 trend 분해.
가장 관심: \(A \times B_{\text{linear}}\) — “처치군이 시간에 따라 다른 변화율?”
10.2 2. 발달 심리학
연령 (within) × 학습 condition (within). 같은 어린이가 여러 연령에서 측정.
10.3 3. 운동학
처치 (within) × 측정 위치 (within) — 같은 사람의 다른 근육에 다른 처치.
10.4 4. ML hyperparameter
같은 모델 architecture × 다른 epoch (시점) 측정. epoch 의 trend.
11 본 시리즈
G-MAX14-0 개관
G-MAX14-1 2×2 D Variable Formation
G-MAX14-2 a×b Extension ← 현재 글
G-MAX14-3 Split-Plot Multivariate + Decision
↓
G-MAX15 (Multilevel — 통합)
12 관련 주제
선행 지식
후속 주제
- G-MAX14-3: Split-Plot Multivariate
- G-MAX15 — Multilevel Models
다른 카테고리 연결
13 더 읽을 거리
- Maxwell, S. E., Delaney, H. D. (2004). “Designing Experiments and Analyzing Data: A Model Comparison Perspective” (2nd ed). Lawrence Erlbaum.
- Davis, C. S. (2002). “Statistical Methods for the Analysis of Repeated Measurements.” Springer — repeated measurements 의 종합.
- Tabachnick, B. G., Fidell, L. S. (2019). “Using Multivariate Statistics” (7th ed). Pearson.
- Hand, D. J., Taylor, C. C. (1987). “Multivariate Analysis of Variance and Repeated Measures.” Chapman & Hall.