1 정의
“Treatment 또는 Outcome 의 직접 원인 (direct cause) 인 모든 변수를 회귀에 통제 변수로 포함한다. 단, treatment 와 outcome 사이의 mediator 는 제외한다.”
(Buisson, 2021, Ch.5; VanderWeele & Shpitser, 2011)
수식:
\[ \text{Controls}_{\text{DCC}} = \underbrace{\{V : V \to T\}}_{\text{T 의 원인}} \cup \underbrace{\{V : V \to Y\}}_{\text{Y 의 원인}} \setminus \underbrace{\{V : T \to V \to Y\}}_{\text{mediator}} \]
“Disjunctive” = “OR” (논리 합).
DCC = “T 의 원인 OR Y 의 원인” 모두 포함 → 둘의 합집합.
대조 (Conjunctive 관점): “T 의 원인 AND Y 의 원인” 만 = confounder 만.
DCC 는 confounder 를 정확히 식별하지 않고도 그것을 포함하는 더 큰 집합을 통제 → confounder 를 빠뜨릴 위험 없음.
→ “Confounder 를 정확히 모를 때 안전한 보험”.
2 개념 및 원리 — DCC 의 4 부분 분해
2.1 1. “모든 직접 원인 (direct cause)”
CD 에서 한 화살표만 거치는 부모 노드.
A ──→ T : A 는 T 의 직접 원인
A ──→ B ──→ T : A 는 T 의 ancestor (간접). DCC 가 직접 요구하지 않음
그러나 chain collapsing 의 효과로:
A ──→ B ──→ T ↔ A ──→ T (collapse)
A 가 chain 을 통해 T 의 effective cause 가 됨. 따라서 DCC 가 “직접 원인” 만 요구해도 chain 을 통해 간접 원인의 효과를 흡수.
DCC 가 “직접 원인” 만 요구하는 이유:
- CD 에서 “A → B → T” 로 표현된 chain 은 collapse 가능 → “A → T” 와 등가
- A 가 직접 원인이든 간접 원인이든 회귀 효과는 동일 (chain 의 양 끝)
- 따라서 직접 원인 통제만으로 confounding path 차단
이 통찰이 DCC 의 효율을 만든다. 모든 ancestor 를 통제할 필요 없음 — 직접 원인만으로 충분.
2.2 2. “T 또는 Y 의” — 두 변수 모두 처리
DCC 가 통제할 변수:
- T 의 원인만 (Y 와 무관) — confounder 아니지만 통제됨 (불필요, but 안전)
- Y 의 원인만 (T 와 무관) — confounder 아니지만 통제됨 (불필요, but 안전)
- T 와 Y 의 공통 원인 (confounder) — 반드시 통제해야 함
핵심: 세 번째 (confounder) 가 첫 번째와 두 번째의 공통 부분에 포함되므로, OR 합집합이 confounder 를 자동 포함.
수학적으로:
\[\{V : V \to T\} \cap \{V : V \to Y\} \subseteq \{V : V \to T\} \cup \{V : V \to Y\}\]
T 의 원인 Y 의 원인
┌──────────┐ ┌──────────┐
│ │ │ │
│ ┌──────┼─────┐ │ │
│ │ │ │ │ │
│ │ Conf │ │ │ │
│ └──────┼─────┘ │ │
│ │ │ │
└──────────┘ └──────────┘
DCC = 두 원의 합집합 (가운데 confounder 포함).
분석가가 confounder 영역을 정확히 모를 때:
- “정확한 confounder 만 통제” → 실수로 빠뜨릴 위험
- “전체 합집합 통제” → 빠뜨림 없이 안전
→ DCC 의 안전 보장 메커니즘.
2.3 3. “Mediator 제외”
T ──→ M ──→ Y
M (mediator) 을 통제하면:
- T 의 직접 효과 (M 우회 경로) 만 추정
- T 의 mediator 경로 효과는 차단됨
- 분석 목적이 “총 효과 (total effect)” 면 이게 잘못된 결과
비유: 도미노 A → B → C 에서 B 를 잡고 있으면 A 가 쓰러져도 C 가 안 쓰러짐. A 의 “총 효과” 가 0 으로 보임.
→ Mediator 는 절대 통제 안 함 (총 효과 분석 시).
MarketingEmail → Engagement → Purchase 구조에서 Engagement 가 mediator.
만약 분석가가 “Engagement 가 강한 confounder” 라고 잘못 식별하고 통제 → over-adjustment, MarketingEmail 의 효과가 가려짐.
이걸 피하려면:
- 시간 선후 점검: T 가 발생한 후 M 이 발생하면 M 은 T 의 자식 → mediator
- 도메인 직관: “M 이 T 의 영향을 받아 Y 에 전달” 의미가 있는가
- 데이터 검증: T 통제 후 M 이 Y 에 강한 영향이면 mediator 가능성
→ Mediator 식별은 분석 설계의 핵심.
2.4 4. “Removes confounding” — 충분 (Sufficient)
DCC 의 보장:
- Sufficient: DCC 의 변수를 모두 통제하면 confounding 제거. 보장됨.
- Not Necessary: DCC 가 요구하는 변수 중 일부는 사실 confounding 에 무관 (Y 만의 원인이거나 T 만의 원인). 통제 안 해도 OK.
→ DCC = “안전 우선” 의 over-engineering. 진짜 필요한 변수보다 더 많이 통제.
비유: 보험. 안 일어날 일에도 보험 들면 비용 발생, 단 일어난다면 보험이 보호.
분석가가 confounder 를 정확히 식별 못할 때:
- “Necessary 만” 통제 시도 → 실수 가능 → confounding 잔존
- “Sufficient 모두” 통제 → 실수해도 confounder 빠뜨림 없음
대신 비용:
- 더 많은 변수 → 더 많은 데이터 필요
- 표준 오차 약간 ↑ (자유도 ↓)
- 계수 해석 부담 ↑
→ 정확도 vs 안전성 trade-off. 분석 초기 단계에서는 안전 우선.
3 DCC 의 강점 — CD 부정확성에 대한 Robust
3.1 CD 의 누락된 화살표를 흡수
마케팅 팀이 CD 를 그렸으나 어떤 화살표를 빠뜨림:
실제 CD:
NumberOfCustomers ──→ IceCreamSales
NumberOfCustomers ──→ BurgerSales ──→ FrenchFrySales ──→ BottledWaterSales
분석가의 CD (위쪽 chain 누락):
NumberOfCustomers ──→ IceCreamSales
FrenchFrySales ──→ BottledWaterSales
분석가는 NumberOfCustomers 가 BottledWaterSales 와 어떻게 연결되는지 모름.
DCC 적용:
- T (IceCreamSales) 의 원인: NumberOfCustomers
- Y (BottledWaterSales) 의 원인: FrenchFrySales
→ NumberOfCustomers + FrenchFrySales 둘 다 통제.
신기한 점: 누락된 chain (NumberOfCustomers → BurgerSales → FrenchFrySales → BottledWaterSales) 의 confounding 을 NumberOfCustomers 통제로 자동 차단.
→ DCC 가 CD 의 부분 부정확성을 보상.
3.2 DCC 의 견고성 (Robustness)
| 분석가의 실수 | 결과 | DCC 가 대응? |
|---|---|---|
| Path 일부 누락 | confounder 식별 실패 | ✓ 다른 cause 통제로 흡수 |
| 화살표 방향 반대로 그림 | confounder 가 아닌 변수 통제 | ✓ 영향 없음 (over-control 만) |
| 일부 confounder 빠뜨림 (변수 자체) | 잔여 confounding | ✗ 변수 자체가 없으면 통제 불가 |
| Mediator 식별 실패 | over-adjustment | ✗ DCC 가 mediator 제외 못 하면 잘못된 추정 |
→ DCC 는 “구조적 실수” 에 robust, “변수 누락” 또는 “mediator 식별 실패” 에는 취약.
4 DCC 의 한계
4.1 한계 1: Redundancy
C-Mart Block 1:
NumberOfCustomers ──→ IceCreamSales
NumberOfCustomers ──→ BurgerSales ──→ FrenchFrySales ──→ BottledWaterSales
IceCreamSales ──→ BottledWaterSales
DCC: NumberOfCustomers + FrenchFrySales 통제.
진짜 필요: NumberOfCustomers 만 (그것만으로 path 자동 차단).
→ FrenchFrySales 통제는 redundant. 자유도 손실, 표준 오차 증가.
이 redundancy 비용은 일반적으로 작지만 변수 많을 때 누적.
4.2 한계 2: 미관측 변수
C-Mart Block 2:
[AverageCustomerAge] ──→ IceCreamSales
[CustomerHealthMindset] ──→ BottledWaterSales
DCC 가 요구: AverageCustomerAge + CustomerHealthMindset 통제.
문제: 두 변수 모두 미관측 (개별 sale 단위 측정 불가).
→ DCC 적용 불가. 분석가는 “잔여 confounding 가능” 명시.
이 한계는 BC 가 보완 (E-BUI5-2). BC 는 collider 의 자연 차단을 활용해 미관측 변수를 우회 가능.
4.3 한계 3: Effect Modifier 처리
M (modifier)
↓
T → Y
M 이 T → Y 효과의 크기를 변경 (예: M = 1 일 때 효과 큼, M = 0 일 때 작음).
DCC 는 M 을 cause of T or Y 로 보면 통제 변수에 포함. 그러나:
- Effect modifier 통제 → 평균 효과 추정 (가능)
- Effect modifier 분석 → 조건부 효과 (subgroup analysis) 필요
DCC 는 후자를 자동으로 안 함. 분석가가 별도로 분리해야.
→ DCC 는 “변수 선택” 만 다루지 “효과의 모형화” 는 별도.
5 응용 — DCC 의 비즈니스 사례
5.1 호텔 NRD 사례
CD (E-BUI4 의 단순화된 버전):
Personal Char PrevCancel ADR Country
↓ ↓ ↓ ↓
└────→ NRDeposit ──→ IsCanceled
└─────────────────────↗
└─────────────────────↗
└─────────────────────↗
NRDeposit 의 직접 원인: Personal Char, PrevCancel, ADR, Country IsCanceled 의 직접 원인: Personal Char, PrevCancel, ADR, Country, NRDeposit Mediator (NRD → ? → Cancel): 없음 (NRD 가 Cancel 의 직접 원인)
DCC: Personal Char + PrevCancel + ADR + Country + (NRD 자체).
회귀:
이게 DCC 처방.
5.2 SaaS Onboarding 사례
CD:
PastExp JobRole Cohort SignupChannel
↓ ↓ ↓ ↓
└────→ Tutorial ──→ Retention
└────────────────────↗
└────────────────────↗
└────────────────────↗
Tutorial 의 직접 원인: PastExp, JobRole, SignupChannel Retention 의 직접 원인: PastExp, JobRole, Cohort, SignupChannel, Tutorial Mediator: 없음
DCC: PastExp + JobRole + Cohort + SignupChannel + Tutorial 통제.
→ Cohort 가 Tutorial 의 원인 아니더라도 (Y 의 원인이므로) DCC 가 통제 요구. 이게 BC 와 차이 (BC 는 Cohort 무시 가능 — 다음 글).
6 DCC 적용 알고리즘
1. CD 확인 (T, Y 결정 + 모든 화살표)
2. T 의 직접 원인 집합 P_T 구하기
3. Y 의 직접 원인 집합 P_Y 구하기
4. Mediator (T → ? → Y 의 중간 노드) 식별
5. 통제 변수 = (P_T ∪ P_Y) \ Mediators \ {T, Y}
이 절차가 알고리즘적이라는 사실 — 자동화 가능.
6.1 DCC 의 Sufficient 증명 (간단 버전)
증명 스케치:
- Confounder C 의 정의: C → T AND C → Y (양방향 화살표 또는 fork)
- DCC 가 T 의 모든 원인 통제 → C 가 T 의 원인이므로 C 통제됨
- C 통제 → T 와 Y 사이 C 를 통한 noncausal path 차단
- Mediator 가 아니므로 T → Y 의 causal path 는 차단 안 됨
- 따라서 confounding 제거.
이 추론에 사용된 가정:
- CD 의 모든 화살표는 정확
- Mediator 는 정확히 식별됨
- 모든 cause 가 측정됨
→ 가정이 깨지면 DCC 도 깨짐. 그러나 일부 화살표 누락에는 robust.
7 코드 예시 — DCC 자동화 + 시뮬레이션
7.1 DCC 식별 자동화
import networkx as nx
def identify_dcc_controls(G, T, Y):
"""
DCC 에 따른 통제 변수 자동 식별.
Parameters
----------
G : networkx.DiGraph
T, Y : str (treatment, outcome 노드 이름)
Returns
-------
set of str (통제 변수)
"""
# Direct causes of T and Y
causes_T = set(G.predecessors(T))
causes_Y = set(G.predecessors(Y))
# Mediators: T → ? → Y
descendants_T = nx.descendants(G, T)
candidates_Y_parents = set(G.predecessors(Y))
mediators = descendants_T & candidates_Y_parents
# DCC = (causes_T ∪ causes_Y) \ mediators \ {T, Y}
controls = (causes_T | causes_Y) - mediators - {T, Y}
return controls
# 호텔 사례
G_hotel = nx.DiGraph()
G_hotel.add_edges_from([
("PersonalChar", "NRDeposit"),
("PersonalChar", "IsCanceled"),
("PrevCancel", "NRDeposit"),
("PrevCancel", "IsCanceled"),
("ADR", "NRDeposit"),
("ADR", "IsCanceled"),
("Country", "NRDeposit"),
("Country", "IsCanceled"),
("NRDeposit", "IsCanceled"),
])
print("=== 호텔 사례 — DCC ===")
controls = identify_dcc_controls(G_hotel, "NRDeposit", "IsCanceled")
print(f"통제 변수: {sorted(controls)}")
print(f" → 회귀: IsCanceled ~ NRDeposit + {' + '.join(sorted(controls))}")분석가가 DCC 를 손으로 적용하면:
- CD 가 복잡할수록 시간 소요
- mediator 식별에 실수 가능
- “혹시 빠뜨린 변수 있나” 불안
자동화:
- 즉시 결과
- 명확한 알고리즘 (재현 가능)
- 분석가는 결과 검토만
→ 비즈니스 분석 파이프라인에 DCC 자동화 함수를 표준화.
7.2 DCC 적용 vs 비적용 비교
import numpy as np
import pandas as pd
import statsmodels.api as sm
np.random.seed(42)
n = 5000
# 데이터 생성
trait = np.random.normal(0, 1, n)
prev_cancel = (trait * 0.5 + np.random.normal(0, 1, n) > 0).astype(int)
adr = trait * 30 + np.random.lognormal(4.5, 0.3, n) * 0.5
country = (trait * 0.3 + np.random.normal(0, 1, n)).clip(-3, 3)
# Treatment
nrd_logit = -3 + 1 * trait + 1.5 * prev_cancel + 0.02 * adr
nrd_prob = 1 / (1 + np.exp(-nrd_logit))
nrd = (np.random.uniform(0, 1, n) < nrd_prob).astype(int)
# Outcome — 진짜 NRD 효과 = 0
cancel_logit = -1 + 0.8 * trait + 0.5 * prev_cancel + 0.01 * adr + 0.0 * nrd
cancel_prob = 1 / (1 + np.exp(-cancel_logit))
cancel = (np.random.uniform(0, 1, n) < cancel_prob).astype(int)
df = pd.DataFrame({
"NRD": nrd, "Cancel": cancel,
"PrevCancel": prev_cancel, "ADR": adr, "Country": country,
})
# 회귀 1: NRD 만
print("=== 회귀 비교 ===")
m1 = sm.Logit(df["Cancel"], sm.add_constant(df["NRD"])).fit(disp=False)
print(f"\n[NRD 만] OR(NRD) = {np.exp(m1.params['NRD']):.2f} (진짜 1)")
# 회귀 2: DCC (PrevCancel, ADR, Country 추가)
m2 = sm.Logit(df["Cancel"], sm.add_constant(df[["NRD", "PrevCancel", "ADR", "Country"]])).fit(disp=False)
print(f"\n[DCC] OR(NRD) = {np.exp(m2.params['NRD']):.2f}")
# 회귀 3: DCC + 잘못된 변수 (mediator 가정)
# 만약 분석가가 잘못해서 NRD → MisuseFlag → Cancel 의 mediator 로 가정한 변수를 통제하면
mediator_misclassified = nrd * 0.5 + np.random.normal(0, 1, n)
df["wrong_mediator"] = mediator_misclassified
m3 = sm.Logit(df["Cancel"], sm.add_constant(df[["NRD", "PrevCancel", "ADR", "Country", "wrong_mediator"]])).fit(disp=False)
print(f"\n[DCC + 잘못 추가] OR(NRD) = {np.exp(m3.params['NRD']):.2f} ← over-adjustment 가능성")예상 결과:
- NRD 만: OR ≈ 3 (강한 양의 가짜 — confounding)
- DCC: OR ≈ 1 (정확)
- DCC + 잘못 추가: OR ≈ 0.5 (over-adjusted)
DCC 가 적절히 적용되면 정확. 그러나 분석가가 추가 변수를 잘못 분류하면 함정.
→ DCC 자동화도 mediator 분류는 분석가의 책임.
7.3 DCC vs Hand-picked 비교
# 비교: DCC (전부) vs 정확한 confounder 만
m_dcc = sm.Logit(
df["Cancel"],
sm.add_constant(df[["NRD", "PrevCancel", "ADR", "Country"]])
).fit(disp=False)
m_minimal = sm.Logit(
df["Cancel"],
sm.add_constant(df[["NRD", "PrevCancel"]]) # 가장 강한 confounder 만
).fit(disp=False)
print("\n=== DCC 전부 vs 핵심 confounder 만 ===")
print(f"DCC 전부: OR = {np.exp(m_dcc.params['NRD']):.3f}, SE = {m_dcc.bse['NRD']:.3f}")
print(f"핵심만: OR = {np.exp(m_minimal.params['NRD']):.3f}, SE = {m_minimal.bse['NRD']:.3f}")
print(f"\nSE 차이: DCC 가 {m_dcc.bse['NRD'] / m_minimal.bse['NRD'] * 100:.1f}% 의 표준 오차")DCC vs 핵심 변수만:
- 점추정: 거의 같음 (DCC 가 약간 더 정확할 가능성)
- 표준 오차: DCC 가 약간 ↑ (불필요한 변수의 자유도 손실)
비즈니스 의사결정:
- 변수 추가의 비용 (SE ↑) 가 작으면 DCC 채택 (안전)
- 비용이 크면 (큰 표본 부족 등) BC 로 변수 최소화
대부분의 비즈니스 분석에서 표본 크기가 충분하므로 DCC 의 SE 비용은 무시 가능.
8 관련 주제
8.1 Ch.5 의 형제 글
- E-BUI5-0 Deconfounding overview — Ch.5 전체 흐름과 DCC vs BC 비교
- E-BUI5-2 백도어 기준과 M-패턴 — BC + M-pattern + Smoking-Seatbelt 사례
8.2 이전 챕터
- E-BUI3-2 체인과 포크 구조 — Confounder 와 Mediator 의 차이
- E-BUI4-3 데이터 검증과 반복 정제 — Ch.4: CD 짓기
8.3 후속 챕터
- E-BUI6-0 결측 데이터 처리 overview — Ch.6: 결측 데이터
- E-BUI12-0 Mediation·IV overview — Ch.12: Mediator 분석
8.4 Hernan 정통 cross-link
- Causal_Inference/07 교란 — Confounder 의 학술적 정의
- Causal_Inference/04 관찰 연구와 식별 조건 — Identification 의 식별성
8.5 카테고리 진입점
- Experimentation 학습 로드맵 — 11 Phase × 7 교재 매핑