In this lecture we introduce causal diagrams—directed acyclic graphs (DAGs)—and connect them to the simulations and identification ideas from the previous lecture. We will
- Define DAGs and basic pieces (nodes, arrows, paths)
- Introduce confounders, colliders, and mediators
- Use Stata simulations to show how conditioning on different variables affects associations
- Connect DAGs back to identification and future regression work
What is a DAG?
A directed acyclic graph (DAG) is:
- A set of nodes (variables)
- Connected by directed arrows (causal relationships)
- With no cycles (you can’t follow arrows and return to the start)
Example:
fert → yield
soil_q → fert
soil_q → yield
Interpretation:
soil_qcausally affects both fertilizer use and yieldfertcausally affects yield
A DAG is your picture of the DGP (assumptions), not something “proven” by the data.
Three key structures
1) Confounder
T ← U → Y
Uis a common cause of treatmentTand outcomeY- If you don’t adjust for
U, the association betweenTandYis confounded
This is what soil_q is in our previous example. It is a common cause of both fert and yield. Rule-of-thumb: you typically do adjust for confounders.
2) Mediator
T → M → Y
Mlies on a causal path fromTtoY- Adjusting for
Mblocks the indirect effect throughM
Rule-of-thumb: for the total effect, you typically do not adjust for mediators but for the direct effect, you do adjust.
3) Collider
T → C ← Y
Cis a common effect ofTandY- Conditioning on
Ccan create a spurious association betweenTandY
Rule-of-thumb: you typically avoid adjusting for colliders.
Confounding simulation: revisited
DAG:
T ← U → Y
* simulate confounding dgp
clear all
set seed 12345
set obs 3000
* confounder
gen U = rnormal(0, 1)
* treatment assignment depends on confounder
gen p_T = invlogit(-0.2 + 1.0*U)
gen T = (runiform() < p_T)
* outcome depends on treatment and confounder
gen eps = rnormal(0, 1)
gen Y = 2 + 1.0*T + 1.5*U + eps
* naive association (confounded)
tabstat Y, by(T) stat(mean n)
* show selection: confounder differs by treatment status
tabstat U, by(T) stat(mean sd n)
* block backdoor path by conditioning on confounder bins
xtile U_q4 = U, nq(4)
forvalues q = 1/4 {
di as text "U_q4 == `q'"
tabstat Y if U_q4 == `q', by(T) stat(mean n)
}
Interpretation:
- Difference in mean
YbyTis biased becauseUshifts bothTandY Udiffers by treatment status, confirming selection intoT- Comparing mean
YbyTwithinUbins (e.g., quartiles) reduces bias by blocking the backdoor pathT ← U → Y
Mediation simulation: total vs direct effects
DAG:
T → M → Y
Simulate:
* simulate mediation DGP
clear all
set seed 1357
set obs 3000
gen train = (runiform() < 0.5)
gen u_s = rnormal(0, 1)
gen skills = 1.0*train + u_s
gen u_w = rnormal(0, 1)
gen wage_lat = 5 + 0.2*train + 0.8*skills + u_w
gen wage = max(wage_lat, 0)
drop wage_lat
* total effect
tabstat wage, by(train) stat(mean n)
* effect on mediator
tabstat skills, by(train) stat(mean n)
* approximate direct effect by comparing within skills bins
xtile skills_q4 = skills, nq(4)
forvalues q = 1/4 {
di as text "skills_q4 == `q'"
tabstat wage if skills_q4 == `q', by(train) stat(mean n)
}
Interpretation:
- Difference in mean wage by training is the total effect
- Within-skills comparisons approximate the direct effect (holding mediator fixed)
Collider bias simulation
DAG:
T → C ← Y
Simulate:
* simulate collider DGP
clear all
set seed 2468
set obs 5000
* T and Y independent in the population
gen T = (runiform() < 0.5)
gen Y = rnormal(0, 1)
* selection depends on both T and Y
gen s_latent = -0.3 + 0.7*T + 0.7*Y + rnormal(0, 1)
gen S = (s_latent > 0)
* check independence in full population
corr T Y
* conditioning on collider (selection)
corr T Y if S == 1
Interpretation:
- In the full sample,
TandYare (approximately) uncorrelated - After restricting to
S==1, you often see a strong correlation: collider bias
Using DAGs to choose adjustment sets
Practical workflow:
- Draw a DAG for your question
- Identify confounders, mediators, colliders
- Decide what effect you want (total vs direct)
- Choose an adjustment strategy consistent with the DAG
This week we implement ideas with simulation + conditional means. Next week regression will implement adjustment sets more directly.
Summary
- Causal diagrams represent structural relationships (nodes and directed arrows) to formalize your DGP.
- Visualizing confounders, colliders, and mediators prevents structural econometric errors.
- They clarify which variables must be conditioned on to achieve causal identification.