1 정의
같은 cluster 의 두 individual 의 outcome 상관 (Buisson, 2021, Ch.10).
수식:
\[ \text{ICC} = \rho = \frac{\sigma^2_{\text{between}}}{\sigma^2_{\text{between}} + \sigma^2_{\text{within}}} \]
해석:
- ICC = 0: cluster 무관 (individuals 독립)
- ICC = 1: cluster 가 모든 variation 설명
- 보통 0.05 ~ 0.5
비즈니스 사례 별 ICC 범위:
| 분야 | ICC 일반 |
|---|---|
| 학교 교육 | 0.10~0.30 |
| 병원 의료 | 0.05~0.20 |
| 매장 운영 | 0.10~0.40 |
| 콜센터 | 0.30~0.60 (high — strong norms) |
ICC 가 높으면 (예: 0.5):
- 같은 cluster 의 individuals 가 매우 비슷
- Cluster 의 norms·culture 강함
- Effective N 이 작음 (cluster 수에 가까움)
ICC 가 낮으면 (예: 0.05):
- 같은 cluster 의 individuals 도 다양
- Effective N ≈ total N
ICC 의 결정:
- 데이터의 cluster 구조의 강도
- 도메인의 social norms
- 측정 metric 의 sensitivity
→ ICC 는 cluster experiment 의 statistical efficiency 의 핵심.
2 Effective Sample Size
2.1 수식 도출
\[ \text{DE} = 1 + (m - 1) \cdot \text{ICC} \]
여기서 \(m\) = cluster 당 평균 individual 수.
Effective N:
\[ n_{\text{eff}} = \frac{n_{\text{total}}}{\text{DE}} = \frac{n_{\text{total}}}{1 + (m - 1) \cdot \text{ICC}} \]
해석:
- DE = 1: ICC = 0 (cluster 무관, \(n_{\text{eff}} = n_{\text{total}}\))
- DE = m: ICC = 1 (cluster 가 모든 정보, $n_{} = $ cluster 수)
- 일반적: 그 사이
AirCnC:
- \(n_{\text{total}} = 695,205\) calls
- \(m = 69,520\) calls/center
- ICC = 0.56
Design Effect:
\[ \text{DE} = 1 + (69519) \cdot 0.56 = 38,931 \]
Effective N:
\[ n_{\text{eff}} = 695205 / 38931 \approx 17.9 \]
해석: 695,205 calls 가 effective N 으로 18 개 unit !
→ 거의 모든 정보가 cluster level. Individual call 수 늘려도 power 미미.
2.2 Cluster 수 vs Cluster 크기
같은 total N 이지만 다른 design:
| Design | Cluster 수 (k) | Cluster 크기 (m) | Total | DE | \(n_{\text{eff}}\) (ICC=0.5) |
|---|---|---|---|---|---|
| A | 10 | 1,000 | 10,000 | 500.5 | 20 |
| B | 100 | 100 | 10,000 | 50.5 | 198 |
| C | 500 | 20 | 10,000 | 10.5 | 952 |
| D | 1,000 | 10 | 10,000 | 5.5 | 1,818 |
| E | 2,000 | 5 | 10,000 | 3.0 | 3,333 |
같은 total N (10,000) 이지만 Effective N 이 20 ~ 3,333 (170 배 차이).
→ Cluster 수 ↑ + Cluster 크기 ↓ = Effective N ↑.
분석가의 결정:
- Total N 을 늘려도 cluster 수 안 늘면 효과 미미
- 비용 효과적: cluster 수 ↑
콜센터 사례:
- 10 콜센터 → 50 콜센터 (5 배)
- \(n_{\text{eff}}\) ≈ 18 → 89 (5 배)
- Power 크게 향상
vs:
- 10 콜센터, calls/center 2 배 (700K → 1.4M)
- \(n_{\text{eff}}\) ≈ 18 → 18.5 (3% 만 ↑)
- Power 거의 변화 없음
→ Cluster 수 늘리는 것이 효과적.
3 AirCnC Power Analysis
3.1 비즈니스 제약
VP 의 요구:
- 실험 기간: 1 개월 (max)
- MDE: 0.6 CSAT
- Power: 가능한 최대
분석가의 도전:
- 1 개월 = ~230,000 calls
- 10 콜센터 = effective N ~ 18
- 0.6 effect 검출에 필요한 power?
답: Permutation-based simulation.
VP 의 제약 = “기다림 vs 정확도” trade-off.
- 1 개월 = 빠른 결정 우선
- MDE 0.6 = “이 정도 효과는 검출하고 싶음”
- Power 제한 가능 (small effect 놓쳐도 OK)
분석가가:
- Power 50% 면 “절반 확률로 implement”
- Power 75% 면 “3/4 확률”
- Power 90% 면 거의 확실
비즈니스 결정:
- 75% 면 충분 (작은 risk 수용)
- 50% 미만이면 더 많은 cluster 필요
이 communication 이 분석가의 역할.
3.2 Permutation Power Simulation
import numpy as np
import statsmodels.formula.api as smf
def cluster_power_perm(hist_data, pairs, effect_size, threshold=0):
"""Permutation-based power."""
n_pairs = len(pairs)
n_perms = 2 ** n_pairs
decisions = []
for perm in range(n_perms):
binary = format(perm, f"0{n_pairs}b")
# 배정
treatment_centers = [
pairs[i][int(b)] for i, b in enumerate(binary)
]
sim = hist_data.copy()
sim["group"] = np.where(
sim["center_ID"].isin(treatment_centers),
"treatment", "control",
)
sim["call_CSAT"] = np.where(
sim["group"] == "treatment",
sim["call_CSAT"] + effect_size,
sim["call_CSAT"],
)
# HLM
try:
mixed = smf.mixedlm(
"call_CSAT ~ group",
data=sim,
groups=sim["center_ID"],
).fit(disp=False)
est = mixed.params.get("group[T.treatment]", 0)
except Exception:
est = 0
decisions.append(1 if est > threshold else 0)
return np.mean(decisions)이 함수가 모든 32 permutation 의 정확한 power 계산.
3.3 CI 의 Discontinuity
96 simulation (32 perm × 3 month) 의 CI 분석:
CI 분포:
[-1.0, -0.5]: 25% (강한 음)
[-0.3, -0.1]: 25% (약한 음)
[+0.1, +0.3]: 25% (약한 양)
[+0.5, +1.0]: 25% (강한 양)
CI 가 4 cluster 로 분리:
- 0 근처 CI 거의 없음
- “Tight clusters” 패턴
이게 stratified cluster 의 statistical 결과:
- 5 pair × 32 perm = limited variability
- 같은 pair 의 두 cluster swap → 효과 추정 변화
- 다른 pair 의 swap → 다른 cluster 의 효과
- 이 조합이 4 distinct values 산출
표준 CI 해석 (CI 가 0 포함하면 no effect):
- 0 근처 CI 거의 없음 → CI 거의 항상 0 미포함
- Standard 의사결정: CI > 0 → implement
- Effect = 0 일 때도 50% 가 양수 CI → false positive 50%!
분석가의 대응:
- CI 의 표준 해석 안 통함
- 임계값 (effect 추정 > X) 으로 의사결정 변경
→ Cluster experiment 의 미묘한 함정. 분석가가 수동 검증 필요.
3.4 Threshold 조정
기본 임계값 (effect > 0):
- False positive: 50% (위에서 본 것)
- True positive (effect 0.6): 75%
수정 임계값 (effect > 0.25):
- False positive: 25% (50% → 25%)
- True positive: 75% (보존)
비즈니스 함의:
- “0.25 미만의 효과는 무시” 의 의미
- VP 의 target = 0.6 → 0.25 임계값 OK
- False positive 25% 는 여전히 큼 (acceptable?)
비즈니스 임계값:
“0.25 CSAT 미만의 개선은 implement 가치 없음.”
분석가의 보고:
“이 SOP 의 추정 효과가 0.25 초과 시 implement. Effect = 0.6 이면 75% 확률로 검출. Effect = 0 이면 25% 확률로 false positive.
25% false positive 가 큰 risk면, 더 많은 cluster (50 콜센터) 또는 더 긴 실험 필요. 현재 제약 (10 cluster, 1 개월) 에서는 이게 최선.”
VP 의 결정:
- 25% risk 수용 → 진행
- 거부 → cluster 늘리거나 다른 design
→ 분석가가 honest 하게 trade-off 보고.
4 Power 와 Confidence 의 Trade-off
4.1 Different Confidence Levels
| Confidence | False Positive | Power (effect 0.6) |
|---|---|---|
| 90% (CI > 0) | 50% | 75% |
| 80% | 35% | 80% |
| 60% | 20% | 85% |
| 40% | 10% | 90% |
낮은 confidence = 좁은 CI = 더 자주 0 미포함:
- False positive ↑
- Power ↑
Stratified individual 실험 (Ch.9):
- 90% CI 가 over-coverage (95% 가 0 포함)
- Free power, low FPR
Stratified cluster 실험 (Ch.10):
- 90% CI 가 under-coverage (50% 가 0 포함)
- Higher FPR, lower power
이유: cluster experiment 의 limited permutations + fixed pair 구조.
→ 두 case 모두 standard 90% CI 가 부정확. 분석가 case-by-case.
4.2 분석가의 결정
흔한 default:
- 90% CI
- α = 0.05
- Power = 0.80
이 default 는 cluster experiment 에 안 맞음.
해결:
- Empirical FPR 측정 (effect = 0 simulation)
- Empirical power 측정 (target effect simulation)
- 임계값 조정 으로 FPR 감소 + power 보존
→ Cluster experiment 는 case-by-case. Standard convention 따르지 말 것.
5 Cluster 수 늘리기 — 비용 효과 분석
5.1 비용 분석
10 cluster vs 50 cluster:
| 비용 | 10 cluster | 50 cluster |
|---|---|---|
| Setup time | 1 주 | 5 주 |
| Training | $50K | $250K |
| Monitoring | $10K/월 | $50K/월 |
| Total (1개월) | $60K | $300K |
5 배 비용 증가.
이익: Power 75% → 95% (estimated, more cluster).
비즈니스 함의:
- 정확도 ↑ vs 비용 ↑ trade-off
- 의사결정 가치가 큰 (예: SOP 변경의 매출 영향 $1M+) 면 추가 비용 OK
- 작은 의사결정 (UI 변경) 이면 부적절
5.2 통합 vs 분리 실험
대안: 작은 실험 → 큰 실험.
Phase 1: 2 콜센터 pilot
- 빠른 trial (1 주)
- Compliance 점검
- 효과 first estimate
- $10K
↓
Phase 2: 10 콜센터 cluster experiment
- Phase 1 의 effect estimate 기반 power 계산
- 1 개월 운영
- $60K
↓
Phase 3: 결정 후 50 콜센터 확장 (선택)
각 단계의 결정:
- Phase 1: 효과 있을 가능성 → 진행
- Phase 2: 정량적 효과 측정 → 결정
- Phase 3: 다른 cluster 에도 효과 있나 검증
→ 단계별이 비용 ↓ + 정보 ↑ + 의사결정 정확.
6 코드 예시 — 통합 Power Analysis
6.1 ICC + Power Curve
import numpy as np
import pandas as pd
import statsmodels.formula.api as smf
import matplotlib.pyplot as plt
def cluster_power_analysis(hist_data, cluster_col, outcome_col,
pairs, effect_grid, threshold=0.25):
"""Cluster experiment 의 종합 power 분석."""
# 1. ICC 계산
empty = smf.mixedlm(
f"{outcome_col} ~ 1",
data=hist_data,
groups=hist_data[cluster_col],
).fit(disp=False)
icc = empty.cov_re.iloc[0, 0] / (empty.cov_re.iloc[0, 0] + empty.scale)
# 2. Effective N
n_total = len(hist_data)
mean_cluster_size = n_total / hist_data[cluster_col].nunique()
n_eff = n_total / (1 + (mean_cluster_size - 1) * icc)
# 3. Power curve at multiple effect sizes
powers = {}
for eff in effect_grid:
# Simulate
decisions = []
n_pairs = len(pairs)
for perm in range(2 ** n_pairs):
binary = format(perm, f"0{n_pairs}b")
treatment_clusters = [
pairs[i][int(b)] for i, b in enumerate(binary)
]
sim = hist_data.copy()
sim["group"] = np.where(
sim[cluster_col].isin(treatment_clusters),
"treatment", "control",
)
sim[outcome_col] = np.where(
sim["group"] == "treatment",
sim[outcome_col] + eff,
sim[outcome_col],
)
try:
mixed = smf.mixedlm(
f"{outcome_col} ~ group",
data=sim,
groups=sim[cluster_col],
).fit(disp=False)
est = mixed.params.get("group[T.treatment]", 0)
except Exception:
est = 0
decisions.append(1 if est > threshold else 0)
powers[eff] = np.mean(decisions)
return {
"icc": icc,
"n_total": n_total,
"n_eff": n_eff,
"powers": powers,
}이 함수의 출력이 분석가에게 주는 것:
- ICC 진단 (cluster 효과 강도)
- Effective N (진짜 표본 크기)
- Power curve (효과 별 검출 능력)
비즈니스 보고:
“ICC = 0.56 (very high). Effective N = 18. Effect 0.6 검출 power = 75% (threshold 0.25).”
이 한 sentence 가 cluster experiment 의 진단.
6.2 Cluster 수의 효과 시뮬레이션
def simulate_more_clusters(hist_data, target_effect, n_clusters_grid,
icc=0.5, residual_var=1.0):
"""더 많은 cluster 의 power 효과 추정."""
results = []
for n_clusters in n_clusters_grid:
# 시뮬레이션 (단순화 — 진짜 historical data 없이)
np.random.seed(42)
n_per = 1000
cluster_baselines = np.random.normal(7, np.sqrt(icc / (1 - icc)), n_clusters)
records = []
for c_idx in range(n_clusters):
for _ in range(n_per):
records.append({
"cluster_ID": f"C{c_idx}",
"csat": cluster_baselines[c_idx] + np.random.normal(0, np.sqrt(residual_var)),
})
df = pd.DataFrame(records)
# 무작위 배정 + 효과
treatment_clusters = np.random.choice(
df["cluster_ID"].unique(), n_clusters // 2, replace=False
)
df["group"] = np.where(
df["cluster_ID"].isin(treatment_clusters), "treatment", "control"
)
df["csat"] = np.where(
df["group"] == "treatment", df["csat"] + target_effect, df["csat"]
)
# HLM
mixed = smf.mixedlm(
"csat ~ group",
data=df,
groups=df["cluster_ID"],
).fit(disp=False)
est = mixed.params.get("group[T.treatment]", 0)
se = mixed.bse.get("group[T.treatment]", 1)
ci_lo = est - 1.645 * se # 90% CI
results.append({
"n_clusters": n_clusters,
"estimate": est,
"se": se,
"ci_lo": ci_lo,
"rejects_zero": ci_lo > 0,
})
return pd.DataFrame(results)
# 시뮬레이션
result = simulate_more_clusters(None, 0.5, [10, 20, 50, 100, 200])
print(result)예상:
| n_clusters | Estimate | SE | CI_lo |
|---|---|---|---|
| 10 | 0.50 | 0.30 | -0.0 |
| 20 | 0.50 | 0.20 | 0.17 |
| 50 | 0.50 | 0.13 | 0.29 |
| 100 | 0.50 | 0.09 | 0.35 |
| 200 | 0.50 | 0.06 | 0.40 |
Cluster 수 ↑ → SE ↓ → CI 넓이 ↓.
비즈니스 결정:
- 10 cluster: borderline (CI 가 0 가까이)
- 50+ cluster: 안정 (CI 정확)
→ 정확도 위해 cluster 수 늘림. 비용 ↑.
6.3 분석가의 보고서
def power_report(result):
"""Power analysis 의 비즈니스 보고."""
print("=" * 60)
print("Cluster Experiment Power Analysis")
print("=" * 60)
print(f"\nICC: {result['icc']:.3f}")
if result['icc'] > 0.3:
print(" → 높은 ICC. Cluster effect 강함.")
elif result['icc'] > 0.1:
print(" → 중간 ICC. Cluster effect 적당.")
else:
print(" → 낮은 ICC. Cluster 무시 가능?")
print(f"\nTotal N: {result['n_total']:,}")
print(f"Effective N: {result['n_eff']:.0f}")
print(f" → Total 의 {result['n_eff']/result['n_total']*100:.1f}% 가 effective")
print("\nPower at various effect sizes:")
for eff, p in result['powers'].items():
bar = "█" * int(p * 20)
print(f" Effect {eff:.2f}: {p:.2%} {bar}")
# 권장
target_power = 0.8
sufficient_effects = [e for e, p in result['powers'].items() if p >= target_power]
if sufficient_effects:
print(f"\n → Power 80%+ 검출 가능 effect: {min(sufficient_effects):.2f} 이상")
else:
print("\n → 80% Power 도달 불가. Cluster 수 ↑ 필요.")이 보고서가 비즈니스 파트너에게:
- ICC 의 의미 (cluster 효과의 강도)
- Effective N (진짜 정보량)
- Power curve (시각적 비교)
- 권장 (충분한 power 위한 effect 또는 cluster 수)
분석가의 결정 도구. 짧은 시간에 power 진단 + 의사결정 보조.
7 Cluster 수의 결정 trade-off
1. ICC 진단 (empty model)
2. Effective N 계산
3. Power curve (다양한 effect 별)
4. 비즈니스 임계값 조정
- Effect 추정값 임계값 (vs 0)
5. Cluster 수 결정
- 충분한 power 가능?
- 추가 cluster 비용 vs 정확도 trade-off
6. Pilot 권장 (단계별)
이 workflow 가 cluster experiment 의 표준.
8 관련 주제
8.1 Ch.10 의 형제 글 (Ch.10 완결)
- E-BUI10-0 군집 무작위 배정 overview — Ch.10 전체 흐름
- E-BUI10-1 군집 사용 시점과 누출 — Cluster 결정
- E-BUI10-2 계층 모형과 임의·고정 효과 — HLM 자세히
8.2 후속 챕터
- E-BUI11-0 Moderation overview — Ch.11: Effect modification
8.3 카테고리 진입점
- Experimentation 학습 로드맵 — 11 Phase × 7 교재 매핑