Math for Causal Inference

Day 51. Interventions & the do-Operator

Seeing is not doing. An intervention do(X = x) replaces X's structural equation, cutting the arrows into X. The truncated factorisation turns this into a formula for the interventional distribution, which differs from ordinary conditioning whenever X has open back-door paths.

Video coming soon
Learning outcomes
  • ●Draw the mutilated graph for an intervention and write the truncated factorisation.
  • ●Compute P(y | do(x)) by adjusting for the parents of X, and compare it with P(y | x).
  • ●Prove that interventions leave non-descendants unchanged and that conditioning equals intervening when X has no parents.
  • ●Evaluate deterministic and stochastic policy interventions in health and economics.
2-HOUR SESSION PLAN
Theory 25′Warm-up (1–5) 20′Proofs (6–10) 35′Applied (11–15) 25′Python & Lab 15′
Colab notebook (.ipynb) Jump to the simulator

Theory

Intervening on a model

An intervention do⁡(X=x)\operatorname{do}(X = x) replaces the structural equation X:=fX(pa⁡(X),UX)X := f_X(\operatorname{pa}(X), U_X) by the constant X:=xX := x, leaving every other equation unchanged. The modified model is Mx\mathcal M_x; its graph GX‾G_{\overline X} is the mutilated graph, with all arrows into XX removed.

The distribution of YY in Mx\mathcal M_x is written P(y∣do⁡(x))P(y \mid \operatorname{do}(x)). It answers "what would happen to YY if we set XX to xx for everyone?"

Seeing versus doing

P(y∣x)P(y \mid x) describes YY among units that happen to have X=xX = x. Those units may differ in other ways (they have different parents of XX). P(y∣do⁡(x))P(y \mid \operatorname{do}(x)) describes the whole population when XX is set to xx. They coincide only when nothing that affects YY also affects XX.

The truncated factorisation

For a Markovian model, delete the factor for XX and plug in X=xX = x everywhere else:

P(v∣do⁡(x))=∏i:Vi≠XP(vi∣pa⁡(vi))∣X=xfor v consistent with x.P(\mathbf v \mid \operatorname{do}(x)) = \prod_{i: V_i \ne X} P\big(v_i \mid \operatorname{pa}(v_i)\big)\Big|_{X = x} \quad \text{for } \mathbf v \text{ consistent with } x.

Adjusting for the parents

Summing the truncated factorisation over everything except YY and the parents PA=pa⁡(X)\mathbf{PA} = \operatorname{pa}(X) gives the adjustment formula

P(y∣do⁡(x))=∑paP(y∣x,pa) P(pa).P(y \mid \operatorname{do}(x)) = \sum_{\mathbf{pa}} P(y \mid x, \mathbf{pa})\,P(\mathbf{pa}).

Compare with conditioning, which weights by P(pa∣x)P(\mathbf{pa} \mid x) instead of P(pa)P(\mathbf{pa}):

P(y∣x)=∑paP(y∣x,pa) P(pa∣x).P(y \mid x) = \sum_{\mathbf{pa}} P(y \mid x, \mathbf{pa})\,P(\mathbf{pa} \mid x).

The difference is exactly confounding. (When the parents are unobserved, Days 52–56 look for other sets.)

Causal effects

The average causal effect of a binary XX is E[Y∣do⁡(X=1)]−E[Y∣do⁡(X=0)]E[Y \mid \operatorname{do}(X = 1)] - E[Y \mid \operatorname{do}(X = 0)]. It is the ATE of Phase 3: in an SCM, the potential outcome is Yi(x)=YY_i(x) = Y computed in Mx\mathcal M_x with unit ii's disturbances (Day 59).

Stochastic (policy) interventions

Real policies rarely force XX on everyone; they shift its distribution, for example a subsidy that raises vaccination rates. Replacing P(x∣pa⁡)P(x \mid \operatorname{pa}) by a new q(x∣pa⁡)q(x \mid \operatorname{pa}) gives

Pq(y)=∑pa,xP(y∣x,pa) q(x∣pa) P(pa).P_q(y) = \sum_{\mathbf{pa}, x} P(y \mid x, \mathbf{pa})\,q(x \mid \mathbf{pa})\,P(\mathbf{pa}).

Part 1 · Warm-up

Exercise 1 · Mutilated graphs

For Z→XZ \to X, Z→YZ \to Y, X→M→YX \to M \to Y, W→XW \to X, draw GX‾G_{\overline X} and GM‾G_{\overline M}.

Show solution

Step 1. GX‾G_{\overline X} removes arrows into XX (Z→XZ \to X, W→XW \to X): left with Z→YZ \to Y, X→M→YX \to M \to Y, and WW isolated.

Step 2. GM‾G_{\overline M} removes X→MX \to M: left with Z→XZ \to X, W→XW \to X, Z→YZ \to Y, M→YM \to Y.

Exercise 2 · Truncated factorisation

Write P(z,m,y∣do⁡(x))P(z, m, y \mid \operatorname{do}(x)) for the graph in Exercise 1 (ignore WW).

Show solution

Step 1. Full factorisation: P(z)P(x∣z)P(m∣x)P(y∣z,m)P(z)P(x \mid z)P(m \mid x)P(y \mid z, m).

Step 2. Drop P(x∣z)P(x \mid z) and fix X=xX = x:

P(z,m,y∣do⁡(x))=P(z) P(m∣x) P(y∣z,m).P(z, m, y \mid \operatorname{do}(x)) = P(z)\,P(m \mid x)\,P(y \mid z, m).

Exercise 3 · Linear seeing versus doing

Z∼N(0,1)Z \sim N(0, 1), X:=Z+UXX := Z + U_X with Var⁡(UX)=1\operatorname{Var}(U_X) = 1, Y:=2X+3Z+UYY := 2X + 3Z + U_Y. Find E[Y∣do⁡(x)]E[Y \mid \operatorname{do}(x)] and E[Y∣X=x]E[Y \mid X = x].

Show solution

Step 1. Doing: ZZ's equation is untouched, so E[Y∣do⁡(x)]=2x+3E[Z]=2xE[Y \mid \operatorname{do}(x)] = 2x + 3E[Z] = 2x.

Step 2. Seeing: E[Z∣X=x]=Cov⁡(Z,X)Var⁡(X)x=12xE[Z \mid X = x] = \dfrac{\operatorname{Cov}(Z, X)}{\operatorname{Var}(X)}x = \dfrac{1}{2}x.

Step 3. E[Y∣X=x]=2x+3⋅12x=3.5xE[Y \mid X = x] = 2x + 3 \cdot \tfrac12 x = 3.5x.

Answer: slope 2 for doing, 3.5 for seeing.

Exercise 4 · No parents, no difference

If XX has no parents (a coin flip), show P(y∣do⁡(x))=P(y∣x)P(y \mid \operatorname{do}(x)) = P(y \mid x) using the adjustment formula.

Show solution

Step 1. With pa⁡(X)=∅\operatorname{pa}(X) = \varnothing the sum has one term: P(y∣do⁡(x))=P(y∣x)P(y \mid \operatorname{do}(x)) = P(y \mid x).

Answer: randomisation makes XX parentless; that is why experiments identify causal effects.

Exercise 5 · Upstream variables do not move

In the graph of Exercise 1, is P(z∣do⁡(x))=P(z)P(z \mid \operatorname{do}(x)) = P(z)? Is P(z∣x)=P(z)P(z \mid x) = P(z)?

Show solution

Step 1. Doing: ZZ is not a descendant of XX, and the truncated factorisation keeps P(z)P(z). Summing out m,ym, y gives P(z∣do⁡(x))=P(z)P(z \mid \operatorname{do}(x)) = P(z).

Step 2. Seeing: Z→XZ \to X, so observing XX is informative about ZZ: in general P(z∣x)≠P(z)P(z \mid x) \ne P(z).

Part 2 · Proofs

Exercise 6 · Truncated factorisation from the SCM

Prove the truncated factorisation for a Markovian SCM.

Show solution

Step 1. Mx\mathcal M_x is again a Markovian SCM: same equations and disturbances for all Vi≠XV_i \ne X, and X:=xX := x (a constant with no parents).

Step 2. By Day 50 (Exercise 6), its distribution factorises over its graph GX‾G_{\overline X}: ∏Vi≠XPMx(vi∣pa⁡(vi))×1[X=x]\prod_{V_i \ne X} P_{\mathcal M_x}(v_i \mid \operatorname{pa}(v_i)) \times \mathbf 1[X = x].

Step 3. For Vi≠XV_i \ne X, the conditional distribution of ViV_i given its parents comes from the same fif_i and UiU_i as in M\mathcal M, so PMx(vi∣pa⁡)=P(vi∣pa⁡)P_{\mathcal M_x}(v_i \mid \operatorname{pa}) = P(v_i \mid \operatorname{pa}). ■\blacksquare

Exercise 7 · The parent adjustment formula

Derive P(y∣do⁡(x))=∑paP(y∣x,pa)P(pa)P(y \mid \operatorname{do}(x)) = \sum_{\mathbf{pa}} P(y \mid x, \mathbf{pa})P(\mathbf{pa}) from the truncated factorisation.

Show solution

Step 1. Multiply and divide the truncated product by P(x∣pa)P(x \mid \mathbf{pa}): P(v∣do⁡(x))=P(v)P(x∣pa)P(\mathbf v \mid \operatorname{do}(x)) = \dfrac{P(\mathbf v)}{P(x \mid \mathbf{pa})} for v\mathbf v consistent with xx.

Step 2. Write P(v)=P(pa)P(x∣pa)P(r∣x,pa)P(\mathbf v) = P(\mathbf{pa})P(x \mid \mathbf{pa})P(\mathbf r \mid x, \mathbf{pa}), where R\mathbf R is all remaining variables, including YY.

Step 3. So P(v∣do⁡(x))=P(pa)P(r∣x,pa)P(\mathbf v \mid \operatorname{do}(x)) = P(\mathbf{pa})P(\mathbf r \mid x, \mathbf{pa}).

Step 4. Sum over pa\mathbf{pa} and over all components of r\mathbf r other than yy: P(y∣do⁡(x))=∑paP(pa)P(y∣x,pa)P(y \mid \operatorname{do}(x)) = \sum_{\mathbf{pa}} P(\mathbf{pa})P(y \mid x, \mathbf{pa}). ■\blacksquare

Exercise 8 · Non-descendants are unaffected

Prove that for any set N\mathbf N of non-descendants of XX, P(n∣do⁡(x))=P(n)P(\mathbf n \mid \operatorname{do}(x)) = P(\mathbf n).

Show solution

Step 1. Order the variables topologically with all non-descendants of XX first. This is possible: no non-descendant has a descendant of XX as an ancestor.

Step 2. The equations of non-descendants involve only other non-descendants and their own disturbances.

Step 3. The intervention changes only XX's equation, and XX is not an input to any non-descendant's equation (directly or indirectly).

Step 4. So the non-descendants are the same functions of the same disturbances in M\mathcal M and Mx\mathcal M_x: their joint distribution is unchanged. ■\blacksquare

Exercise 9 · Conditional ignorability from the SCM

In a Markovian SCM, prove that the potential outcome Y(x)Y(x) is independent of XX given pa⁡(X)\operatorname{pa}(X).

Show solution

Step 1. In Mx\mathcal M_x, XX's equation is gone, so Y(x)Y(x) is a function of the disturbances other than UXU_X: Y(x)=g(U−X)Y(x) = g(\mathbf U_{-X}).

Step 2. pa⁡(X)\operatorname{pa}(X) is a function of the disturbances of its ancestors, also in U−X\mathbf U_{-X}.

Step 3. X=fX(pa⁡(X),UX)X = f_X(\operatorname{pa}(X), U_X). Given pa⁡(X)=p\operatorname{pa}(X) = \mathbf p, X=fX(p,UX)X = f_X(\mathbf p, U_X) depends only on UXU_X.

Step 4. UXU_X is independent of U−X\mathbf U_{-X}, also after conditioning on an event defined by U−X\mathbf U_{-X} (the event pa⁡(X)=p\operatorname{pa}(X) = \mathbf p).

Step 5. So given pa⁡(X)\operatorname{pa}(X), XX is independent of Y(x)Y(x). ■\blacksquare This is Phase 3's unconfoundedness, derived from a graph.

Exercise 10 · Conditioning is a weighted adjustment

Show that P(y∣x)−P(y∣do⁡(x))=∑paP(y∣x,pa)[P(pa∣x)−P(pa)]P(y \mid x) - P(y \mid \operatorname{do}(x)) = \sum_{\mathbf{pa}} P(y \mid x, \mathbf{pa})\big[P(\mathbf{pa} \mid x) - P(\mathbf{pa})\big], and give two conditions under which it is zero.

Show solution

Step 1. By the law of total probability, P(y∣x)=∑paP(y∣x,pa)P(pa∣x)P(y \mid x) = \sum_{\mathbf{pa}} P(y \mid x, \mathbf{pa})P(\mathbf{pa} \mid x).

Step 2. Subtract the adjustment formula term by term.

Step 3. Zero if P(pa∣x)=P(pa)P(\mathbf{pa} \mid x) = P(\mathbf{pa}) for all values (XX independent of its parents, as under randomisation).

Step 4. Zero if P(y∣x,pa)P(y \mid x, \mathbf{pa}) does not depend on pa\mathbf{pa} (the parents do not affect YY except through XX). ■\blacksquare

Part 3 · Applied

Exercise 11 · Vaccination: seeing versus doing

Use Day 47's flu model: 30% are older; P(V=1∣old)=0.8P(V = 1 \mid \text{old}) = 0.8, P(V=1∣young)=0.4P(V = 1 \mid \text{young}) = 0.4; infection risks young unvaccinated 0.10, young vaccinated 0.04, old unvaccinated 0.30, old vaccinated 0.12. Compute P(I=1∣do⁡(V=1))P(I = 1 \mid \operatorname{do}(V = 1)) and P(I=1∣do⁡(V=0))P(I = 1 \mid \operatorname{do}(V = 0)) and compare with the observed 0.077 and 0.125.

Show solution

Step 1. Age is the only parent of VV. Adjust: P(I=1∣do⁡(V=1))=0.7(0.04)+0.3(0.12)=0.028+0.036=0.064P(I = 1 \mid \operatorname{do}(V = 1)) = 0.7(0.04) + 0.3(0.12) = 0.028 + 0.036 = 0.064.

Step 2. P(I=1∣do⁡(V=0))=0.7(0.10)+0.3(0.30)=0.07+0.09=0.16P(I = 1 \mid \operatorname{do}(V = 0)) = 0.7(0.10) + 0.3(0.30) = 0.07 + 0.09 = 0.16.

Step 3. Causal risk ratio 0.064/0.16=0.400.064/0.16 = 0.40; risk difference −0.096-0.096.

Answer: universal vaccination would cut the infection rate from 16% to 6.4%. The observed comparison (7.7% vs 12.5%, ratio 0.62) understates the benefit, because the vaccinated are older.

Exercise 12 · A vaccination subsidy

A subsidy raises vaccination among the young from 40% to 70%, leaving the old at 80%. Using Exercise 11's model, what infection rate does the policy produce, compared with 10% now?

Show solution

Step 1. Stochastic intervention: replace P(V=1∣young)=0.4P(V = 1 \mid \text{young}) = 0.4 by q=0.7q = 0.7.

Step 2. Young: 0.7×[0.7(0.04)+0.3(0.10)]=0.7×0.058=0.04060.7 \times [0.7(0.04) + 0.3(0.10)] = 0.7 \times 0.058 = 0.0406.

Step 3. Old (unchanged): 0.3×[0.8(0.12)+0.2(0.30)]=0.3×0.156=0.04680.3 \times [0.8(0.12) + 0.2(0.30)] = 0.3 \times 0.156 = 0.0468.

Step 4. Total: 0.0406+0.0468=0.08740.0406 + 0.0468 = 0.0874.

Answer: about 8.7% instead of 10%, a 1.3-point reduction. The policy effect depends on whom the subsidy reaches, which a single ATE does not tell you.

Exercise 13 · Fertiliser and yields

On farms, rainfall R∼N(0,1)R \sim N(0, 1) affects both fertiliser use F:=0.5R+UFF := 0.5R + U_F (Var⁡(UF)=0.75\operatorname{Var}(U_F) = 0.75) and yields Y:=2F+3R+UYY := 2F + 3R + U_Y. A regression of yields on fertiliser alone finds what slope? What is the effect of a fertiliser subsidy that raises FF by one unit on every farm?

Show solution

Step 1. Var⁡(F)=0.25+0.75=1\operatorname{Var}(F) = 0.25 + 0.75 = 1 and Cov⁡(F,R)=0.5\operatorname{Cov}(F, R) = 0.5.

Step 2. Seeing: E[Y∣F=f]=2f+3E[R∣F=f]=2f+3(0.5f)=3.5fE[Y \mid F = f] = 2f + 3E[R \mid F = f] = 2f + 3(0.5f) = 3.5f. Slope 3.5.

Step 3. Doing: E[Y∣do⁡(F=f+1)]−E[Y∣do⁡(F=f)]=2E[Y \mid \operatorname{do}(F = f + 1)] - E[Y \mid \operatorname{do}(F = f)] = 2.

Answer: the regression overstates the yield response by 75%, because farmers use more fertiliser in wet years, which are also good years.

Exercise 14 · Should hospitals close intensive care units?

20% of patients are severe. P(ICU∣severe)=0.9P(\text{ICU} \mid \text{severe}) = 0.9 and P(ICU∣mild)=0.1P(\text{ICU} \mid \text{mild}) = 0.1. Death risks: mild without ICU 0.02, mild in ICU 0.01, severe without ICU 0.40, severe in ICU 0.25. Compute observed mortality with and without ICU care, and the mortality under do(ICU) and do(no ICU).

Show solution

Step 1. P(ICU)=0.8(0.1)+0.2(0.9)=0.26P(\text{ICU}) = 0.8(0.1) + 0.2(0.9) = 0.26.

Step 2. Seeing, ICU: 0.8(0.1)(0.01)+0.2(0.9)(0.25)0.26=0.0008+0.0450.26≈0.176\dfrac{0.8(0.1)(0.01) + 0.2(0.9)(0.25)}{0.26} = \dfrac{0.0008 + 0.045}{0.26} \approx 0.176.

Step 3. Seeing, no ICU: 0.8(0.9)(0.02)+0.2(0.1)(0.40)0.74=0.0144+0.0080.74≈0.030\dfrac{0.8(0.9)(0.02) + 0.2(0.1)(0.40)}{0.74} = \dfrac{0.0144 + 0.008}{0.74} \approx 0.030.

Step 4. Doing: P(D∣do⁡(ICU))=0.8(0.01)+0.2(0.25)=0.058P(D \mid \operatorname{do}(\text{ICU})) = 0.8(0.01) + 0.2(0.25) = 0.058; P(D∣do⁡(no ICU))=0.8(0.02)+0.2(0.40)=0.096P(D \mid \operatorname{do}(\text{no ICU})) = 0.8(0.02) + 0.2(0.40) = 0.096.

Answer: ICU patients die six times as often (17.6% vs 3.0%), yet giving everyone ICU care would cut mortality from 9.6% to 5.8%. Severity is a parent of both admission and death.

Exercise 15 · Seeing or doing?

Classify each question as a conditional (seeing) or interventional (doing) query: (a) "What share of microfinance borrowers start a business?"; (b) "How much would business creation rise if every household got a loan?"; (c) "Do workers who join a union earn more?"; (d) "What would happen to wages if union membership became mandatory?"; (e) "Which patients with a positive test actually have the disease?"

Show solution

Step 1. (a) Seeing: P(B∣L=1)P(B \mid L = 1).

Step 2. (b) Doing: P(B∣do⁡(L=1))−P(B)P(B \mid \operatorname{do}(L = 1)) - P(B).

Step 3. (c) Seeing: E[W∣U=1]−E[W∣U=0]E[W \mid U = 1] - E[W \mid U = 0].

Step 4. (d) Doing: E[W∣do⁡(U=1)]E[W \mid \operatorname{do}(U = 1)].

Step 5. (e) Seeing: P(D∣T=+)P(D \mid T = +), a diagnostic question answered by Bayes' rule (Day 2); no intervention is involved.

Verify in Python

import numpy as np

# Exercises 11-12: vaccination
pOld = .3; pV = {"young": .4, "old": .8}
risk = {("young", 0): .10, ("young", 1): .04, ("old", 0): .30, ("old", 1): .12}
w = {"young": 1 - pOld, "old": pOld}
do = {v: sum(w[a] * risk[a, v] for a in w) for v in (0, 1)}
see = {v: sum(w[a] * (pV[a] if v else 1 - pV[a]) * risk[a, v] for a in w) / sum(w[a] * (pV[a] if v else 1 - pV[a]) for a in w) for v in (0, 1)}
print("do:", {k: round(x, 4) for k, x in do.items()}, " see:", {k: round(x, 4) for k, x in see.items()})
q = {"young": .7, "old": .8}
print("infection with subsidy:", round(sum(w[a] * (q[a] * risk[a, 1] + (1 - q[a]) * risk[a, 0]) for a in w), 4))

# Exercise 13: fertiliser, by simulation of the SCM and of the intervened SCM
rng = np.random.default_rng(51); n = 1_000_000
R = rng.normal(size=n); F = .5 * R + np.sqrt(.75) * rng.normal(size=n); Y = 2 * F + 3 * R + rng.normal(size=n)
print("observational slope:", round(np.polyfit(F, Y, 1)[0], 3))
Y1 = 2 * (F + 1) + 3 * R + rng.normal(size=n)       # do(F := F + 1) for every farm
print("effect of +1 unit:", round((Y1 - Y).mean(), 3))

# Exercise 14: ICU
pS = .2; pICU = {0: .1, 1: .9}; d = {(0, 0): .02, (0, 1): .01, (1, 0): .40, (1, 1): .25}   # key (severe, icu)
ws = {0: 1 - pS, 1: pS}
for icu in (0, 1):
    num = sum(ws[s] * (pICU[s] if icu else 1 - pICU[s]) * d[s, icu] for s in (0, 1))
    den = sum(ws[s] * (pICU[s] if icu else 1 - pICU[s]) for s in (0, 1))
    print(f"ICU={icu}: seeing {num / den:.4f}  doing {sum(ws[s] * d[s, icu] for s in (0, 1)):.4f}")

Key takeaways

  • do⁡(X=x)\operatorname{do}(X = x) deletes XX's equation and the arrows into XX; everything else stays the same.
  • With observed parents, P(y∣do⁡(x))=∑paP(y∣x,pa)P(pa)P(y \mid \operatorname{do}(x)) = \sum_{\mathbf{pa}} P(y \mid x, \mathbf{pa})P(\mathbf{pa}); conditioning instead weights by P(pa∣x)P(\mathbf{pa} \mid x).
  • Policies are often stochastic interventions: they shift P(x∣pa⁡)P(x \mid \operatorname{pa}) rather than fix xx.

Simulation Lab: Seeing vs Doing: the ICU

Open full screen →

ICU patients die more often, yet admitting everyone saves lives: conditional versus interventional mortality.

SeverityICUDeathseeing: P(death | ICU)0.176seeing: P(death | no ICU)0.030doing: P(death | do(ICU))0.058doing: P(death | do(no ICU))0.096
observed difference
0.146
P(D|ICU) − P(D|no ICU)
causal effect
-0.038
do(ICU) − do(no ICU)

Severity drives both ICU admission and death. Seeing compares patients who happened to be admitted with those who were not; doing sets admission for everyone, cutting the arrow from severity into ICU (the mutilated graph) and averaging over the population's severity mix.

Day 50Day 52