The Question

Act I

What if people ignore the treatment they were assigned?

A lottery or a coin flip decides who should be treated — that is the clean experiment of Chapter 1.

But police officers override their orders, patients skip their pills, and lottery winners never enroll. What is left of the experiment?

Comparing people by the treatment they received brings selection bias back

prompts

raises

causal effect?

Dangerous incident

Officer arrests

Repeat violence

Whoever decides to deviate from the plan does so for a reason — and that reason may also drive the outcome.

Our route through the chapter

  • The question — why non-compliance breaks a simple comparison of treated and untreated
  • The investigation — the IV chain reaction, the three conditions for a valid instrument, who LATE speaks for, and three case studies: police responses, a charter-school lottery, family size
  • The resolution — 2SLS in practice, weak instruments, and the traps to avoid

Every IV analysis has three variables

Instrument \(Z\)

The random nudge — a lottery win, an assignment form.

Treatment \(D\)

What people actually received — the action taken, the school attended.

Outcome \(Y\)

What we care about — repeat violence, test scores, years of schooling.

IV uses the randomness in \(Z\) to learn how \(D\) affects \(Y\).

Three measurements and four kinds of people carry the chapter

The measurements

  • First stage — how much \(Z\) moves \(D\)
  • Reduced form — how much \(Z\) moves \(Y\)
  • LATE — the effect of \(D\) on \(Y\) for those \(Z\) moves

The people

  • Compliers — follow the nudge
  • Always-takers — treated no matter what
  • Never-takers — untreated no matter what
  • Defiers — do the opposite

The method is built from the left column; its interpretation depends on the right.

The Investigation

Act II

Assigned treatment and received treatment are two different variables

Assigned (\(Z\))

  • Decided by the researcher’s lottery
  • Random by design
  • Like a doctor’s prescription

Received (\(D\))

  • Decided by people on the ground
  • Can depend on anything — including risk
  • Like the pill actually swallowed

Non-compliance is the gap between the two columns — and only the left one is guaranteed random.

Minneapolis police were randomly told to arrest, advise, or separate

Assigned response What the officer should do Cases
Arrest Take the suspect into custody 92
Advise Counsel or mediate the couple 108
Separate Send the suspect away for 8 hours 114

The goal: learn which response best prevents future domestic violence.

Officers obeyed arrest orders almost always, and the others far less

Form said Arrest Advise Separate Obeyed
Arrest 91 0 1 98.9%
Advise 19 84 5 77.8%
Separate 26 5 83 72.8%

Rows: the randomly assigned response · columns: what the officer actually did.

When officers deviated, they almost always deviated toward arrest.

pd.crosstab shows who followed the form

import pandas as pd                              # pandas → load and tabulate

# every course dataset lives in the repo's data/ folder on GitHub
GITHUB_DATA_URL = "https://raw.githubusercontent.com/cmg777/intro2causal/main/data/"
mdve = pd.read_csv(GITHUB_DATA_URL + "ch3/mdve_clean.csv")   # 314 MDVE cases

# rows = what the form said, columns = what officers did; shares within each row
pd.crosstab(mdve["assigned"], mdve["delivered"], normalize="index").round(3)

↗ Try it in Colab

IV works like a chain of dominoes

first stage

causal effect

reduced form

Instrument Z: random form

Treatment D: police action

Outcome Y: repeat violence

We see the first domino fall and the last one fall; IV infers the push in between.

First stage and reduced form are two simple comparisons by \(Z\)

\[\phi = E[D_i \mid Z_i = 1] - E[D_i \mid Z_i = 0]\]

\[\rho = E[Y_i \mid Z_i = 1] - E[Y_i \mid Z_i = 0]\]

\(\phi\): how far the nudge moves treatment. \(\rho\): how far it moves the outcome. Both are clean, because \(Z\) is random.

Both comparisons inherit the experiment’s randomization — neither uses the treatment people chose.

Dividing the reduced form by the first stage isolates the treatment effect

\[\lambda_{LATE} = \frac{\rho}{\phi} = \frac{\text{effect of } Z \text{ on } Y}{\text{effect of } Z \text{ on } D}\]

If the nudge moves only part of the group, its effect on \(Y\) is diluted by the same fraction — so we scale it back up.

LATE = reduced form ÷ first stage: the Wald ratio.

The idea dates back to 1928, to untangle supply from demand

  • Philip G. Wright, in an appendix to a book on tariffs, used outside factors that shift one curve but not the other
  • His son Sewall Wright, a geneticist, supplied the path-diagram mathematics
  • The idea then lay largely dormant for decades

Instruments are “external factors” that move one part of a system while leaving the rest alone.

Relevance and independence can be checked in the data

Relevance

  • \(Z\) must actually move \(D\)
  • Check: a strong first stage
  • MDVE: the form moved actual coddling a lot

Independence

  • \(Z\) must be as good as randomly assigned
  • Check: balance across \(Z\) groups
  • MDVE, KIPP: a lottery guarantees it by design

Two of the three conditions leave fingerprints we can inspect.

Exclusion: the instrument may reach the outcome only through the treatment

forbidden

forbidden

Wins KIPP lottery (Z)

Attends KIPP (D)

Math score (Y)

Parents feel motivated

No data test can rule out a side channel — exclusion must be argued, not proven.

An instrument sorts people into four types

Type If \(Z = 0\) If \(Z = 1\) What IV learns about them
Complier untreated treated Their effect = LATE
Always-taker treated treated Nothing (unmoved)
Never-taker untreated untreated Nothing (unmoved)
Defier treated untreated Ruled out by assumption

Only people whose treatment responds to the instrument contribute to the IV estimate.

Monotonicity rules out defiers, and MDVE crossovers run one way

Crossover direction Cases Rate
Told to coddle → arrested 45 of 222 20.3%
Told to arrest → coddled 1 of 92 1.1%

Officers bent the rules toward arrest, almost never away from it — consistent with no defiers.

LATE speaks for the compliers and stays silent about everyone else

  • The “L” in LATE means local — local to the people the instrument moves
  • Always-takers and never-takers may have very different effects
  • A different instrument moves a different group, so it can give a different LATE

Before generalizing an IV estimate, ask: who are the compliers here?

MDVE: recode three arms as “coddle” versus “arrest”

Variable Code name Equals 1 when…
Instrument \(Z\) z_coddle form said advise/separate
Treatment \(D\) d_coddle officer advised/separated
Outcome \(Y\) (published) repeat violence occurred

One binary instrument and one binary treatment fit the standard IV formula.

Assignment to coddle raised actual coddling by 79 points

Share actually coddled
Form said coddle (\(Z = 1\)) 0.797
Form said arrest (\(Z = 0\)) 0.011
First stage \(\phi\) (difference) 0.786

A first stage this large means the random form had real power over what officers did.

One pf.feols call estimates the first stage and its strength

!pip install -q pyfixest                         # pyfixest is not preinstalled in Colab
import pandas as pd                              # pandas → load tables
import pyfixest as pf                            # pyfixest → regressions with robust SEs

GITHUB_DATA_URL = "https://raw.githubusercontent.com/cmg777/intro2causal/main/data/"
mdve = pd.read_csv(GITHUB_DATA_URL + "ch3/mdve_clean.csv")   # 314 MDVE cases

mdve["z_coddle"] = (mdve["assigned"] != "Arrest").astype(int)    # Z: form said coddle
mdve["d_coddle"] = (mdve["delivered"] != "Arrest").astype(int)   # D: officer coddled

fs = pf.feols("d_coddle ~ z_coddle", data=mdve, vcov="hetero")   # first stage, robust SEs
fs.summary()                  # z_coddle 0.786 (SE 0.029), t ≈ 27 → F = t² ≈ 727

↗ Try it in Colab

Coddling raises repeat violence by 14.5 points for compliers

Step Value
First stage \(\phi\) (from the data) 0.786
Reduced form \(\rho\) (published rates: 0.211 − 0.097) 0.114
LATE \(= \rho / \phi\) 0.145
Naive gap by treatment received 0.087

IV finds a bigger harm from coddling than the naive 8.7-point gap — selection bias was hiding it.

The Wald ratio is a single division

import pandas as pd                              # pandas → load tables
# every course dataset lives in the repo's data/ folder on GitHub
GITHUB_DATA_URL = "https://raw.githubusercontent.com/cmg777/intro2causal/main/data/"
mdve = pd.read_csv(GITHUB_DATA_URL + "ch3/mdve_clean.csv")   # 314 MDVE cases

z = mdve["assigned"] != "Arrest"                 # Z: form said coddle (True/False)
d = mdve["delivered"] != "Arrest"                # D: officer actually coddled

phi = d[z].mean() - d[~z].mean()                 # first stage: 0.797 − 0.011 = 0.786
rho = 0.211 - 0.097                              # reduced form: published repeat-violence rates
print(rho / phi)                                 # LATE ≈ 0.145 → +14.5 points for compliers

↗ Try it in Colab

KIPP Lynn’s oversubscribed lottery created a ready-made instrument

  • KIPP: charter schools with long days and a “no excuses” culture
  • KIPP Lynn (Massachusetts) had more applicants than seats after 2005 → seats by lottery
  • \(Z\) = won the lottery · \(D\) = attended KIPP · \(Y\) = math test score

Validity check: lottery winners and losers looked alike at baseline — the balance check passes.

A school lottery is an experiment with built-in non-compliance: some winners decline, some losers get in later.

Winning the lottery raised math scores by 0.355 standard deviations

IV component Estimate
First stage: lottery win → attended KIPP 0.741
Reduced form: lottery win → math score +0.355 SD
LATE: attending KIPP → math score +0.48 SD

Dividing 0.355 by 0.741 converts the effect of winning into the effect of attending.

One year at KIPP, for lottery compliers

+0.48 SD

in math — about half a standard deviation in a single year

Children from bigger families get less schooling, but is that causal?

  • Quantity–quality story: more children → less parental investment per child
  • OLS: each extra sibling goes with −0.15 years of schooling
  • Confounder: less-educated parents tend to have more children and less-educated children

The naive slope may just be telling us about the parents, not about family size.

Two accidents of birth shift family size almost at random

Twins at the second birth

  • An unplanned extra child
  • First stage: +0.32 children

Same-sex first two children

  • Parents try again for a mix of boys and girls
  • First stage: +0.08 children

Both instruments move family size for reasons unrelated to how educated the parents are.

The reduced forms are near zero, and 2SLS flips the sign

Estimate Effect of one more sibling on schooling
OLS (naive) −0.15 years
Reduced form, each instrument about zero
2SLS, both instruments +0.24 (SE 0.13)

Once family size changes by chance, the education penalty disappears — the OLS slope was selection bias.

2SLS does the IV job in two regressions

Stage 1 — predict treatment from the instrument:

\[D_i = \alpha_1 + \phi Z_i + \gamma_1 X_i + e_{1i}\]

Stage 2 — regress the outcome on the predicted treatment:

\[Y_i = \alpha_2 + \lambda_{2SLS} \hat{D}_i + \gamma_2 X_i + e_{2i}\]

\(\hat{D}_i\) keeps only the part of treatment driven by the instrument; \(X_i\) are optional controls.

With one binary instrument and no controls, 2SLS reproduces the Wald ratio exactly.

Hand-rolled 2SLS gets the coefficient right but the standard errors wrong

  • Running two separate feols calls by hand: right \(\hat\lambda\), wrong SE
  • The second stage treats \(\hat{D}_i\) as data, ignoring that it was estimated
  • Dedicated IV software corrects this automatically

Always run 2SLS as one IV call: pf.feols("y ~ 1 | d ~ z").

pf.feols runs 2SLS in one formula and beats OLS on confounded data

!pip install -q pyfixest                             # pyfixest is not preinstalled in Colab
import numpy as np, pandas as pd, pyfixest as pf     # simulate · tabulate · regress

rng, n = np.random.default_rng(42), 10_000           # fixed seed → same numbers every run
df = pd.DataFrame({"u": rng.normal(size=n),          # u: hidden confounder (motivation)
                   "z": rng.integers(0, 2, size=n)}) # z: coin-flip instrument (a lottery)
df["d"] = (1.5*df.z + df.u + rng.normal(size=n) > 0.75).astype(int)  # d: nudged by z, chosen on u
df["y"] = 0.5*df.d + df.u + rng.normal(size=n)       # y: the TRUE effect of d is 0.5

print(pf.feols("y ~ d", data=df, vcov="hetero").coef()["d"])          # OLS ≈ 1.48: biased by u
print(pf.feols("y ~ 1 | d ~ z", data=df, vcov="hetero").coef()["d"])  # 2SLS ≈ 0.48: near the truth

↗ Try it in Colab

A weak first stage makes IV unreliable: check that \(F > 10\)

  • Weak instrument: \(Z\) barely moves \(D\), so we divide by a number near zero
  • Consequences: estimates biased toward OLS, misleading confidence intervals
  • Rule of thumb: first-stage \(F\)-statistic above 10

MDVE first stage: \(t \approx 27\), so \(F = t^2 \approx 727\) — nowhere near weak.

Check the first stage before trusting any IV estimate.

Pick the design that matches the variation you have

RCT (Chapter 1) OLS with controls IV / 2SLS
Needs Random assignment of treatment Confounders all observed A valid instrument
Handles All confounders Only observed confounders Unobserved confounders
Estimates ATE (everyone) Conditional association LATE (compliers)
Weakness Costly, often impractical Fails with hidden confounders Needs a strong, valid instrument

IV trades breadth for credibility: a clean answer, but only for the compliers.

The Resolution

Act III

The tempting mistake: “IV recovers the effect for everyone”

Objection. The lottery is random, so the IV estimate is the average effect of treatment in the whole population.

Response. IV only sees people whose treatment the instrument changed. KIPP’s +0.48 SD is the effect for lottery compliers; always-takers and never-takers may respond quite differently.

The tempting mistake: “A huge sample cures a weak instrument”

Objection. The first stage is small, but we have millions of observations — precision will take care of it.

Response. Weak-instrument bias does not shrink as the sample grows. With a first-stage \(F\) below 10, 2SLS can sit close to the biased OLS answer. The cure is a stronger instrument.

Key takeaways

  • Comparing by treatment received brings back selection bias
  • LATE = reduced form ÷ first stage, for compliers only
  • A valid instrument is relevant, as good as random, and works through one channel
  • Run 2SLS with IV software (pf.feols) and check the first-stage F
  • KIPP: large math gains · family size: no harm to schooling

A random nudge, scaled by how far it moves treatment, reveals the causal effect for those it moves.