다중 조절 변수와 부트스트랩 — Parallel·Interacting Moderators 와 CI 검증 (Buisson Ch.11.3)

여러 moderator 의 처리, Moderated Moderation, Bootstrap CI 의 우월성

Buisson (2021) Ch.11 의 Multiple Moderators + Bootstrap 절을 자세히 정리한다. Parallel Moderators 의 회귀 + 해석, Interacting Moderators (Moderated Moderation), 3-way interaction 의 정량화, Bootstrap CI 의 우월성, 다중 moderator 의 검증 절차를 단계별로 시연한다.

Experimentation
Causal Inference
저자

Kwangmin Kim

공개

2026년 05월 08일

1 정의

정의: Parallel vs Interacting Moderators

여러 moderator 가 한 효과에 영향을 미칠 때 (Buisson, 2021, Ch.11):

  1. Parallel Moderators: 여러 moderator 가 독립적으로 효과 modify
  2. Interacting Moderators (Moderated Moderation): 한 moderator 의 효과가 다른 moderator 에 의존

수식:

Parallel:
   Y = β_0 + β_X X + β_M1 M1 + β_M2 M2 + β_i1 (X*M1) + β_i2 (X*M2)

Moderated Moderation:
   Y = β_0 + β_X X + ... + β_i1 (X*M1) + β_i2 (X*M2) + β_3way (X*M1*M2)

3-way interaction term 이 moderated moderation 의 핵심.

직관 — 두 형태의 차이

비유: 운동 효과의 moderation.

Parallel:

  • 성별 (M1) 이 운동 효과 modify
  • 나이 (M2) 도 운동 효과 modify
  • 두 moderator 가 독립적으로 작동
  • 남자 효과 별도, 노인 효과 별도

Moderated Moderation:

  • 성별 의 효과 modify 정도 가 나이에 따라 다름
  • “젊은 남자: 운동 +10kg, 노인 남자: 운동 +5kg”
  • 성별의 moderation 자체가 나이 dependent

→ Parallel 은 단순, moderated moderation 은 복잡 (3-way interaction).

2 Parallel Moderators

2.1 C-Mart 사례 — Children + Age

두 독립 moderator

PlayArea 의 visit duration 효과를 두 변수가 modify:

Children (Y/N) ─→
                  ↘
        PlayArea ──→ VisitDuration
                  ↗
   Age (numeric) ─→

수식:

\[ \text{Duration} = \beta_0 + \beta_p P + \beta_c C + \beta_a A + \beta_{pc} (P \cdot C) + \beta_{pa} (P \cdot A) \]

해석:

  • \(\beta_{pc}\): Children 이 PA 의 효과 modify
  • \(\beta_{pa}\): Age 가 PA 의 효과 modify
  • 두 modification 은 독립적
직관 — 독립의 의미

“독립적 moderation” 의 의미:

  • Children 의 modification 효과 = 모든 age 에서 동일
  • Age 의 modification 효과 = 모든 children 상태에서 동일

수학적으로:

\[ \text{Effect of P at (C, A)} = \beta_p + \beta_{pc} C + \beta_{pa} A \]

각 모더레이션이 별도로 추가.

비교: Moderated moderation 은 children 의 modification 자체가 age 에 따라 다름 (다음 절).

2.2 Age 의 numeric 처리

Numeric vs Categorical

Age 가 numeric (연속 변수) 인 경우:

  • \(\beta_{pa}\) = “Age 1 살 차이당 PA 효과 차이”

해석:

  • \(\beta_{pa} > 0\): 나이 들수록 PA 효과 큼
  • \(\beta_{pa} < 0\): 어릴수록 PA 효과 큼
  • \(\beta_{pa} = 0\): Age 무관

대안: Age 를 binning 으로 categorical 처리.

df["age_group"] = pd.cut(df["age"], bins=[0, 30, 50, 100],
                          labels=["young", "middle", "old"])

각 그룹의 \(\beta\) 별도 추정.

직관 — Numeric vs Categorical 의 trade-off
처리 장점 단점
Numeric Parsimonious (1 coefficient), 정량적 Linear 가정
Categorical (binned) 비선형 가능, 해석 쉬움 변수 수 ↑, 임의 binning

분석가의 결정:

  • Linear 관계 가정 OK → numeric
  • 비선형 의심 + 큰 sample → categorical

비즈니스 보고:

  • 의사결정 → categorical (해석 쉬움, “young 에 큰 효과”)
  • 정량 → numeric (continuous 효과)

→ 분석 목적에 따라.

2.3 회귀 코드

Multiple * operators

R:

lm(duration ~ play_area * children + play_area * age, data=df)

Python:

import statsmodels.formula.api as smf

m = smf.ols(
    "duration ~ play_area * children + play_area * age",
    data=df,
).fit()
print(m.summary())

* 가 별도 interaction 추가:

  • play_area * children → main effects + play_area:children
  • play_area * age → main effects + play_area:age

3-way (PA × C × A) interaction 은 추가 안 됨 (parallel 가정).

직관 — Formula 의 명시적 의미

play_area * children + play_area * age 의 의미:

  • play_area + children + play_area:children + age + play_area:age
  • 6 terms (intercept 제외)

3-way 자동 추가 안 함:

  • 그것은 play_area * children * age (다음 절)

분석가가 의도 명확히:

  • Parallel: + 로 분리 (독립 moderator)
  • Moderated moderation: * 로 결합 (interacting)

3 Moderated Moderation (Interacting Moderators)

3.1 정의

3-way Interaction

Children 의 PA 효과 modification 이 Age 에 따라 다름.

비즈니스 직관:

  • Young 부모 + 자녀: PA 의 효과 큼 (child 가 PA 사용 좋아함)
  • Old 조부모 + 손자녀: PA 의 효과 작음 (잘 안 씀)

수식:

\[ \text{Duration} = \beta_0 + \beta_p P + \beta_c C + \beta_a A + \beta_{pc} (PC) + \beta_{pa} (PA) + \beta_{ca} (CA) + \beta_{pca} (PCA) \]

3-way interaction term: \(\beta_{pca} (P \cdot C \cdot A)\).

이 term 이 moderated moderation 의 핵심.

직관 — 3-way 의 직관

비유: 약물의 효과.

  • 약물 X 가 환자에게 효과
  • 효과는 체중 (M1) 에 따라 다름
  • 나이 (M2) 에 따라 체중 효과의 modification 이 또 다름

3-way interaction:

  • Age 별로 weight × treatment 의 interaction 이 다름
  • “젊은 환자: 체중 무관, 노인: 체중 ↑ → 효과 ↓”

비즈니스에서 흔함:

  • Marketing campaign × demographic1 × demographic2
  • Pricing × seasonality × customer type

3.2 R / Python 코드

Triple *

R:

lm(duration ~ play_area * children * age, data=df)

Python:

smf.ols(
    "duration ~ play_area * children * age",
    data=df,
).fit()

자동 확장:

play_area + children + age
+ play_area:children
+ play_area:age
+ children:age
+ play_area:children:age   ← 3-way (moderated moderation)

8 terms (intercept 제외).

함정 — 너무 많은 항

3-way interaction:

  • 8 terms = 큰 변수 수
  • 작은 sample 에서 unstable
  • Multicollinearity 위험

분석가의 default:

  • 큰 sample (10K+) 만 3-way 사용
  • Pre-registered 가설 우선
  • Bootstrap CI 로 robust 검증

3.3 결과 해석

Buisson 의 사례 (가상)
                              Estimate
(Intercept)                   20.02
play_area                      3.91
children                       9.99
age                            ~0
play_area:children            29.16
play_area:age                  ~0  (not significant)
children:age                   ~0  (not significant)
play_area:children:age         ~0  (not significant)

해석:

  • Children 의 modification 효과 = 29.16 (큼)
  • Age 의 main effect 거의 0
  • Age 의 interaction 효과 거의 0 (모든 case)
  • 3-way 거의 0 → moderated moderation 약함

결론: PlayArea 의 효과가 Children 에 강하게 의존. Age 는 무관.

→ 단순화: 회귀에서 Age 관련 term 제거 가능.

직관 — 결과의 비즈니스 함의

이 분석이 비즈니스 의사결정에:

  • Age 별 정책 차별화 불필요
  • Children 별 정책 차별화 핵심
  • Targeting: 자녀 동반 customer 에 PA 우선

만약 3-way 가 통계적·실용적 유의 시:

  • “젊은 부모 + 자녀: PA 큰 효과”
  • “조부모 + 손자녀: PA 작은 효과”
  • 더 정밀한 segmentation 필요

→ 분석가가 단계별 simplification.

3.4 시각화

직관 — Subgraph plot

Buisson 의 Figure 11-19 같은 visualization:

  • X-axis: Children (0, 1)
  • Y-axis: Average Duration
  • 8 subgraph: age 별 (20, 30, 40, 50, 60, 70, 80)
  • 각 subgraph: 두 line (PA = 0, 1)
import matplotlib.pyplot as plt
import seaborn as sns

g = sns.FacetGrid(df, col="age_group", col_wrap=4, height=3)
g.map_dataframe(
    lambda data, **kwargs: sns.pointplot(
        data=data, x="children", y="duration", hue="play_area"
    )
)
plt.savefig("moderated_moderation.png")
plt.show()

각 subgraph 의 두 line 의 거리 차이가 moderated moderation 의 visual 증거.

4 Bootstrap CI 의 우월성

4.1 P-value vs CI

P-value 의 한계

전통 회귀의 p-value:

  • Normal distribution 가정
  • Standard error 가 계수 분포 정규일 때만 정확
  • Interaction term 의 분포는 보통 skewed → p-value 부정확

Bootstrap CI:

  • 분포 가정 없음
  • Robust to skewed/heavy-tailed
  • Interaction 같은 비선형 통계량에 적합
Bootstrap CI 함수
import numpy as np

def bootstrap_interaction_CI(df, formula, target_term, B=1000, conf=0.9):
    """Interaction term 의 Bootstrap CI."""
    coeffs = []
    for _ in range(B):
        sample = df.sample(len(df), replace=True)
        m = smf.ols(formula, data=sample).fit()
        coeff = m.params.get(target_term, np.nan)
        if not np.isnan(coeff):
            coeffs.append(coeff)
    coeffs.sort()
    lo = coeffs[int(B * (1 - conf) / 2)]
    hi = coeffs[int(B * (1 + conf) / 2)]
    return lo, hi


# 사용
ci = bootstrap_interaction_CI(
    df, "duration ~ play_area * children", "play_area:children", B=1000, conf=0.9,
)
print(f"play_area:children 90% CI: [{ci[0]:.2f}, {ci[1]:.2f}]")
직관 — Bootstrap 의 정확성

Bootstrap CI 의 procedural 단계:

  1. 원본 데이터에서 같은 크기 (with replacement) sample
  2. 회귀 적합
  3. Interaction coefficient 추출
  4. B 번 반복
  5. Coefficients 의 quantile

장점:

  • 분포 가정 없음
  • 각 sample 의 다양성으로 robust 추정
  • Skewed/heavy-tailed 분포에 작동

비즈니스 분석에서 default 도구.

4.2 CI 의 비즈니스 해석

CI 의 의미

가상 결과:

play_area:children 90% CI: [27.5, 30.8]

해석:

  • “Interaction 의 진짜 값이 [27.5, 30.8] 사이일 가능성 90%”
  • 0 미포함 → 통계적 유의
  • 27.5 자체가 비즈니스적으로 큰 → 실용적 유의

만약 CI 가 0 포함:

play_area:children 90% CI: [-0.5, 1.2]
  • 0 포함 → 통계적 유의 안 함
  • “Interaction 효과 있을 수도, 없을 수도”
  • 더 큰 sample 필요 또는 효과 작음

비즈니스 의사결정:

  • CI 좁고 0 미포함 → 진행
  • CI 넓고 0 포함 → 추가 데이터 또는 보수적 결정
직관 — CI 의 communication

분석가의 보고:

“PlayArea × Children interaction = 29.16 (90% CI [27.5, 30.8]). 자녀 동반 customer 의 PA 효과가 자녀 없는 customer 보다 평균 29 분 더 김. CI 가 좁고 0 미포함 → 통계적·실용적으로 강한 effect. 자녀 동반 매장 우선 PA 설치 권장.”

이 한 paragraph 이 분석의 핵심 산출물.

5 Multiple Moderators 의 Bootstrap

5.1 Joint CI

여러 interaction 의 동시 검증

Parallel moderators 의 회귀:

m = smf.ols(
    "duration ~ play_area * children + play_area * age",
    data=df,
).fit()

여러 interaction terms:

  • play_area:children
  • play_area:age

Bootstrap 으로 동시 검증:

def bootstrap_multiple_interactions(df, formula, terms, B=1000, conf=0.9):
    """여러 interaction terms 의 Bootstrap CI 동시."""
    results = {term: [] for term in terms}

    for _ in range(B):
        sample = df.sample(len(df), replace=True)
        m = smf.ols(formula, data=sample).fit()
        for term in terms:
            results[term].append(m.params.get(term, np.nan))

    cis = {}
    for term, coeffs in results.items():
        coeffs = sorted([c for c in coeffs if not np.isnan(c)])
        lo = coeffs[int(B * (1 - conf) / 2)]
        hi = coeffs[int(B * (1 + conf) / 2)]
        cis[term] = (lo, hi)

    return cis
직관 — 동시 검증의 가치

각 interaction 별 CI 비교:

  • play_area:children CI: [27, 31] — 강한 effect
  • play_area:age CI: [-0.5, +0.5] — 효과 없음

분석가의 결정:

  • Children 은 강한 moderator → 비즈니스 분석에 통합
  • Age 는 무관 → 단순화 (회귀에서 제거)

이 검증이 모형 선택 가이드.

6 다중 모더레이터의 함정

6.1 False Discovery Rate

여러 moderator 시도의 위험

100 가지 가능 moderator 시도 → 평균 5 개 false positive (α = 0.05).

다중 검정 보정:

  1. Bonferroni: \(\alpha_{adj} = \alpha / N_{tests}\)
  2. Holm-Bonferroni: 순차 조정 (덜 보수적)
  3. FDR (Benjamini-Hochberg): false discovery rate 통제

Buisson 의 권장: Bonferroni 안 사용.

이유:

  • NHST framework 에 의존
  • 너무 보수적 → false negative 증가
  • 비즈니스 분석에 부적합
직관 — Buisson 의 대안

“Promising moderator 발견 시 follow-up 실험으로 검증.”

이 권장의 가치:

  • Bonferroni 의 conservatism 회피
  • 실험으로 직접 confirmation
  • 비즈니스 가치 있는 효과만 검증

Workflow:

  1. 1 차 분석: 여러 moderator 시도 (탐색적)
  2. Promising 발견 (large effect, narrow CI)
  3. 2 차 실험: 그 moderator 정식 검증
  4. Pre-registered hypothesis
  5. 결과 → 의사결정

→ 발견은 가설, 검증은 confirmation.

6.2 Provisional Hypotheses

직관 — 비즈니스 파트너 communication

분석가의 보고:

“1 차 분석에서 promising moderator 발견: Children 이 PA 효과 큰 modify (CI [27, 31]). 이는 provisional hypothesis — 추가 검증 필요.

권장: 1. Follow-up 실험 (children-focused) 2. Pre-registered hypothesis 3. 결과 따라 implementation 결정.

1 차 분석 결과만으로 정책 변경하지 말 것.”

이 framing 이:

  • 분석가의 신뢰성 보호
  • 비즈니스 파트너에게 정확한 risk 전달
  • False positive 위험 줄임

→ Discovery 와 Confirmation 의 분리.

7 코드 예시 — 종합

7.1 Parallel Moderators

import numpy as np
import pandas as pd
import statsmodels.formula.api as smf

# 가상 데이터
np.random.seed(42)
n = 5000
df = pd.DataFrame({
    "play_area": np.random.binomial(1, 0.5, n),
    "children": np.random.binomial(1, 0.4, n),
    "age": np.random.uniform(20, 80, n),
})

# True coefficients
beta_0 = 20
beta_p = 4
beta_c = 10
beta_a = 0  # age main 무관
beta_pc = 25
beta_pa = -0.05  # 약한 negative (older 효과 약간 작음)

df["duration"] = (
    beta_0 + beta_p * df["play_area"]
    + beta_c * df["children"] + beta_a * df["age"]
    + beta_pc * df["play_area"] * df["children"]
    + beta_pa * df["play_area"] * df["age"]
    + np.random.normal(0, 5, n)
)

m = smf.ols(
    "duration ~ play_area * children + play_area * age",
    data=df,
).fit()
print(m.summary().tables[1])
직관 — 추정 결과의 검증

예상:

  • \(\hat{\beta}_p \approx 4\)
  • \(\hat{\beta}_{pc} \approx 25\)
  • \(\hat{\beta}_{pa} \approx -0.05\)
  • 모두 진짜 값에 가까움

분석가의 다음 단계:

  • \(\beta_{pc}\) 의 큰 effect → 자녀 segmentation 핵심
  • \(\beta_{pa}\) 의 작은 effect → age modification 미미

7.2 Bootstrap CI 적용

def bootstrap_multi(df, formula, terms, B=1000, conf=0.9):
    """여러 term 의 Bootstrap CI."""
    results = {t: [] for t in terms}
    for _ in range(B):
        sample = df.sample(len(df), replace=True)
        m = smf.ols(formula, data=sample).fit()
        for t in terms:
            results[t].append(m.params.get(t, np.nan))
    return {
        t: (np.percentile(c, 5), np.percentile(c, 95))
        for t, c in results.items() if c
    }


cis = bootstrap_multi(
    df,
    "duration ~ play_area * children + play_area * age",
    ["play_area:children", "play_area:age"],
)
print("\n=== Bootstrap CI ===")
for term, (lo, hi) in cis.items():
    print(f"  {term}: [{lo:.3f}, {hi:.3f}]")

7.3 직관 — CI 의 결정

예상:

  • play_area:children CI: [23, 27] — 0 미포함, 강함
  • play_area:age CI: [-0.08, -0.02] — 0 미포함이지만 작은 effect

분석가의 결론:

  • Children moderator: 통계적·실용적 유의 → 핵심
  • Age moderator: 통계적 유의 + 작은 effect → 무시

비즈니스 의사결정:

  • Children-focused targeting
  • Age 는 marketing 시 소소한 조정 only

7.4 Moderated Moderation

# 3-way interaction
np.random.seed(42)
n = 5000
df_3 = pd.DataFrame({
    "play_area": np.random.binomial(1, 0.5, n),
    "children": np.random.binomial(1, 0.4, n),
    "age_group": np.random.choice(["young", "middle", "old"], n),
})

# True (moderated moderation)
df_3["duration"] = 20 + 4 * df_3["play_area"]
df_3["duration"] += 10 * df_3["children"]

# Children moderation 이 age 에 따라 다름
modifier = np.where(
    df_3["age_group"] == "young", 30,
    np.where(df_3["age_group"] == "middle", 20, 5),
)
df_3["duration"] += modifier * df_3["play_area"] * df_3["children"]
df_3["duration"] += np.random.normal(0, 5, n)

# 회귀
m_3 = smf.ols(
    "duration ~ play_area * children * age_group",
    data=df_3,
).fit()
print(m_3.summary().tables[1])

7.5 직관 — 3-way 의 결과

예상 추정:

  • play_area:children (baseline = young): ~30
  • play_area:children:age_group[T.middle]: ~-10
  • play_area:children:age_group[T.old]: ~-25

해석:

  • Young: PA × Children effect = 30 (큼)
  • Middle: PA × Children effect = 20 (중간)
  • Old: PA × Children effect = 5 (작음)

비즈니스 함의:

  • Young 부모 동반 매장 → PA 큰 효과
  • Old (조부모) 동반 매장 → PA 작은 효과
  • Targeting 을 demographic + life stage 별 정밀화

8 종합 — 분석가의 결정 트리

8.1 다중 Moderator 결정

1. 사전 가설 (도메인 직관)
   - 어떤 moderator 들이 있을 가능성?
   - 1~3 개 후보

2. Parallel 시도
   - 회귀: X * M1 + X * M2
   - 각 interaction 의 Bootstrap CI
   - 통계적·실용적 유의 점검

3. Moderated Moderation 가설
   - 도메인 직관: M1 의 modification 이 M2 에 따라 다름?
   - Yes 면 3-way interaction 추가

4. 3-way 회귀
   - X * M1 * M2
   - Bootstrap CI 의 3-way term

5. 단순화
   - 무관 term 제거
   - Parsimony 우선

6. Provisional 결과
   - 1 차 분석 = 가설
   - 2 차 실험 = 검증
   - Discovery vs Confirmation 분리

7. Final 보고
   - 비즈니스 implications
   - CI 의 정직한 communication
   - Provisional 한 부분 명시

이 워크플로가 다중 moderator 의 표준.

9 관련 주제

9.1 Ch.11 의 형제 글 (Ch.11 완결)

9.2 이전 챕터

9.3 후속 챕터

9.4 카테고리 진입점

Subscribe

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