Math for Causal Inference

Day 67. Difference-in-Differences: the 2×2 Case

Compare how outcomes changed in a treated group with how they changed in an untreated group. Under parallel trends, the difference in changes is the effect of treatment on the treated. The estimand, its regression form, and the assumptions that make or break it.

Video coming soon
Learning outcomes
  • ●Compute the 2×2 difference-in-differences estimate from four means and from a regression with an interaction.
  • ●Prove that DiD identifies the ATT under parallel trends and no anticipation.
  • ●Show that parallel trends depend on the scale of the outcome (levels versus logs).
  • ●Apply DiD to minimum wages, health insurance expansions and training programmes, and spot failures such as the Ashenfelter dip.
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

Set-up

Two groups (G=1G = 1 treated, G=0G = 0 comparison) and two periods (T=0T = 0 before, T=1T = 1 after). Only the treated group in period 1 receives treatment. The target is the ATT in the post period:

ATT=E[Y1(1)−Y1(0)∣G=1],ATT = E[Y_{1}(1) - Y_{1}(0) \mid G = 1],

where Yt(d)Y_t(d) is the potential outcome in period tt. The problem: E[Y1(0)∣G=1]E[Y_1(0) \mid G = 1], what would have happened to the treated without treatment, is unobserved.

Two naive comparisons

  • Before–after in the treated group: E[Y1−Y0∣G=1]E[Y_1 - Y_0 \mid G = 1], biased by anything else that changed over time.
  • Treated–comparison after: E[Y1∣G=1]−E[Y1∣G=0]E[Y_1 \mid G = 1] - E[Y_1 \mid G = 0], biased by permanent group differences.

Assumption (parallel trends): without treatment, the average outcome would have changed by the same amount in both groups:

E[Y1(0)−Y0(0)∣G=1]=E[Y1(0)−Y0(0)∣G=0].E[Y_1(0) - Y_0(0) \mid G = 1] = E[Y_1(0) - Y_0(0) \mid G = 0].

No anticipation: Y0=Y0(0)Y_0 = Y_0(0) for the treated (treatment does not affect pre-period outcomes).

The DiD estimand

Under both assumptions,

ATT=(E[Y1∣G=1]−E[Y0∣G=1])−(E[Y1∣G=0]−E[Y0∣G=0]).ATT = \big(E[Y_1 \mid G = 1] - E[Y_0 \mid G = 1]\big) - \big(E[Y_1 \mid G = 0] - E[Y_0 \mid G = 0]\big).

The comparison group's change is the counterfactual change for the treated.

Regression form

Yit=α+γGi+λTt+δ (Gi×Tt)+εit.Y_{it} = \alpha + \gamma G_i + \lambda T_t + \delta\,(G_i \times T_t) + \varepsilon_{it}.

The four cell means are α\alpha, α+λ\alpha + \lambda, α+γ\alpha + \gamma, α+γ+λ+δ\alpha + \gamma + \lambda + \delta; so δ^\hat\delta is exactly the DiD of sample means. With panel data, regressing ΔYi\Delta Y_i on GiG_i gives the same number. Covariates can be added (for instance pre-treatment characteristics interacted with TT), and standard errors should be clustered at the level at which treatment is assigned.

Scale matters

Parallel trends in levels and in logs cannot both hold unless baseline levels are equal or there is no trend. The choice of scale is a substantive assumption, not a technicality.

Threats

Different shocks to the two groups in the post period; selection into treatment based on transitory outcomes (the Ashenfelter dip: people join training after a temporary earnings drop, which would have recovered anyway); compositional changes in repeated cross-sections; spillovers to the comparison group.

Part 1 · Warm-up

Exercise 1 · Four means

Treated: 40 before, 52 after. Comparison: 35 before, 41 after. Compute the DiD.

Show solution

Step 1. Treated change: 52−40=1252 - 40 = 12.

Step 2. Comparison change: 41−35=641 - 35 = 6.

Step 3. DiD: 12−6=612 - 6 = 6.

Exercise 2 · Regression coefficients

Using Exercise 1's means, give α,γ,λ,δ\alpha, \gamma, \lambda, \delta in the regression form.

Show solution

Step 1. α=35\alpha = 35 (comparison, before).

Step 2. γ=40−35=5\gamma = 40 - 35 = 5 (group gap before).

Step 3. λ=41−35=6\lambda = 41 - 35 = 6 (comparison trend).

Step 4. δ=52−(35+5+6)=6\delta = 52 - (35 + 5 + 6) = 6, the DiD.

Exercise 3 · The naive comparisons

With Exercise 1's means, compute the before–after and post-period cross-sectional comparisons, and say what biases each.

Show solution

Step 1. Before–after: 12; includes the common trend of 6.

Step 2. Cross-section after: 52−41=1152 - 41 = 11; includes the permanent gap of 5.

Answer: both overstate the effect (6); DiD removes both biases under parallel trends.

Exercise 4 · Levels or logs?

Comparison: 10 → 12. Treated: 20 → 25. Compute DiD in levels and in logs. If the treated would have grown by the comparison group's percentage, what is the effect in levels?

Show solution

Step 1. Levels: (25−20)−(12−10)=3(25 - 20) - (12 - 10) = 3.

Step 2. Logs: ln⁡(25/20)−ln⁡(12/10)=0.223−0.182=0.041\ln(25/20) - \ln(12/10) = 0.223 - 0.182 = 0.041.

Step 3. Under proportional (log) parallel trends, the treated counterfactual is 20×1.2=2420 \times 1.2 = 24, so the effect is 25−24=125 - 24 = 1.

Answer: 3 under level trends, 1 under proportional trends: the scale assumption triples the estimate.

Exercise 5 · Anticipation

A tax cut announced a year ahead is evaluated with DiD using the announcement year as "before". Why might this be a problem?

Show solution

Step 1. Firms may change behaviour once the cut is announced (for example, delaying investment until it takes effect).

Step 2. Then the "before" outcome is already affected: no anticipation fails.

Answer: use a baseline before the announcement.

Part 2 · Proofs

Exercise 6 · DiD identifies the ATT

Prove that under parallel trends and no anticipation the DiD estimand equals the ATT.

Show solution

Step 1. Observed outcomes: E[Y1∣G=1]=E[Y1(1)∣G=1]E[Y_1 \mid G = 1] = E[Y_1(1) \mid G = 1]; E[Y0∣G=1]=E[Y0(0)∣G=1]E[Y_0 \mid G = 1] = E[Y_0(0) \mid G = 1] (no anticipation); comparison outcomes are untreated potential outcomes.

Step 2. DiD =E[Y1(1)−Y0(0)∣G=1]−E[Y1(0)−Y0(0)∣G=0]= E[Y_1(1) - Y_0(0) \mid G = 1] - E[Y_1(0) - Y_0(0) \mid G = 0].

Step 3. By parallel trends, replace the second term by E[Y1(0)−Y0(0)∣G=1]E[Y_1(0) - Y_0(0) \mid G = 1].

Step 4. DiD =E[Y1(1)−Y1(0)∣G=1]=ATT= E[Y_1(1) - Y_1(0) \mid G = 1] = ATT. ■\blacksquare

Exercise 7 · The interaction coefficient

Prove that OLS of the saturated regression Y=α+γG+λT+δGT+εY = \alpha + \gamma G + \lambda T + \delta GT + \varepsilon gives δ^=(Yˉ11−Yˉ10)−(Yˉ01−Yˉ00)\hat\delta = (\bar Y_{11} - \bar Y_{10}) - (\bar Y_{01} - \bar Y_{00}), with Yˉgt\bar Y_{gt} the cell means.

Show solution

Step 1. The regression has four parameters and four cells: it is saturated, so fitted values equal cell means.

Step 2. Fitted values: Yˉ00=α^\bar Y_{00} = \hat\alpha, Yˉ01=α^+λ^\bar Y_{01} = \hat\alpha + \hat\lambda, Yˉ10=α^+γ^\bar Y_{10} = \hat\alpha + \hat\gamma, Yˉ11=α^+γ^+λ^+δ^\bar Y_{11} = \hat\alpha + \hat\gamma + \hat\lambda + \hat\delta.

Step 3. Solve: δ^=Yˉ11−Yˉ10−Yˉ01+Yˉ00\hat\delta = \bar Y_{11} - \bar Y_{10} - \bar Y_{01} + \bar Y_{00}. ■\blacksquare

Exercise 8 · First differences

With a balanced panel, show that regressing ΔYi=Yi1−Yi0\Delta Y_i = Y_{i1} - Y_{i0} on a constant and GiG_i gives the DiD estimate.

Show solution

Step 1. A regression on a constant and a binary variable gives the difference in group means of the outcome.

Step 2. β^G=ΔY‾G=1−ΔY‾G=0=(Yˉ11−Yˉ10)−(Yˉ01−Yˉ00)\hat\beta_G = \overline{\Delta Y}_{G=1} - \overline{\Delta Y}_{G=0} = (\bar Y_{11} - \bar Y_{10}) - (\bar Y_{01} - \bar Y_{00}). ■\blacksquare

Without parallel trends, show DiD =ATT+Δ= ATT + \Delta, where Δ=E[Y1(0)−Y0(0)∣G=1]−E[Y1(0)−Y0(0)∣G=0]\Delta = E[Y_1(0) - Y_0(0) \mid G = 1] - E[Y_1(0) - Y_0(0) \mid G = 0].

Show solution

Step 1. From Exercise 6, Step 2: DiD =E[Y1(1)−Y0(0)∣G=1]−E[Y1(0)−Y0(0)∣G=0]= E[Y_1(1) - Y_0(0) \mid G = 1] - E[Y_1(0) - Y_0(0) \mid G = 0].

Step 2. Add and subtract E[Y1(0)∣G=1]E[Y_1(0) \mid G = 1]: DiD =ATT+E[Y1(0)−Y0(0)∣G=1]−E[Y1(0)−Y0(0)∣G=0]= ATT + E[Y_1(0) - Y_0(0) \mid G = 1] - E[Y_1(0) - Y_0(0) \mid G = 0]. ■\blacksquare

Exercise 10 · Scale dependence

Suppose untreated outcomes grow by the same proportion g>0g > 0 in both groups and baseline means differ (μ1≠μ0\mu_1 \ne \mu_0). Show that parallel trends in levels fails.

Show solution

Step 1. Untreated change for group kk: μk(1+g)−μk=gμk\mu_k(1 + g) - \mu_k = g\mu_k.

Step 2. Difference between groups: g(μ1−μ0)≠0g(\mu_1 - \mu_0) \ne 0.

Answer: level trends differ by g(μ1−μ0)g(\mu_1 - \mu_0), which is exactly the level-DiD bias. ■\blacksquare

Part 3 · Applied

Exercise 11 · The New Jersey minimum wage

In Card and Krueger's study, average full-time-equivalent employment per fast-food restaurant was 20.44 before and 21.03 after New Jersey raised its minimum wage, and 23.33 and 21.17 in neighbouring eastern Pennsylvania. Compute the DiD and state the identifying assumption.

Show solution

Step 1. New Jersey change: 21.03−20.44=0.5921.03 - 20.44 = 0.59.

Step 2. Pennsylvania change: 21.17−23.33=−2.1621.17 - 23.33 = -2.16.

Step 3. DiD: 0.59−(−2.16)=2.750.59 - (-2.16) = 2.75.

Answer: about +2.75 FTE workers per restaurant, no evidence of job loss. Identifying assumption: without the increase, New Jersey restaurants would have followed Pennsylvania's employment trend.

Exercise 12 · Medicaid expansion and mortality

Adult mortality per 100,000 fell from 320 to 310 in states that expanded Medicaid and from 330 to 328 in states that did not. Estimate the effect and give one threat to parallel trends.

Show solution

Step 1. Expansion change: −10. Non-expansion change: −2.

Step 2. DiD: −10−(−2)=−8-10 - (-2) = -8 deaths per 100,000.

Step 3. Threat: expansion states may have been on a different health trajectory (different opioid epidemics, economic recoveries).

Answer: −8 per 100,000, credible only if pre-expansion mortality trends were similar (Day 68 checks this).

Exercise 13 · A pre-period placebo for bed nets

Malaria cases per 1,000 children in districts that received a bed-net campaign in 2020: 2018: 150, 2019: 140, 2021: 100. In comparison districts: 2018: 160, 2019: 155, 2021: 140. Compute a placebo DiD for 2018–2019 and the main DiD for 2019–2021. Interpret.

Show solution

Step 1. Placebo: treated change 140−150=−10140 - 150 = -10; comparison 155−160=−5155 - 160 = -5; placebo DiD =−5= -5.

Step 2. Main: treated 100−140=−40100 - 140 = -40; comparison 140−155=−15140 - 155 = -15; DiD =−25= -25.

Step 3. The placebo shows the treated districts were already improving 5 cases faster per year.

Answer: −25 per 1,000, but with a pre-trend; if the extra −5 per year continued over two years, a trend-adjusted estimate would be about −25+10=−15-25 + 10 = -15 (Day 68 formalises this).

Exercise 14 · Inference with two states

The New Jersey study compares restaurants in two states. Why are conventional standard errors (treating restaurants as independent) too optimistic, and what can be done?

Show solution

Step 1. Any state-specific shock in the post period hits all restaurants in that state together: errors are correlated within state.

Step 2. With one treated and one comparison cluster, cluster-robust SEs cannot be computed reliably.

Answer: use more comparison units (many states or counties), randomisation inference across placebo states, or synthetic control methods (Day 85); be explicit that with two clusters the uncertainty is understated.

Exercise 15 · The Ashenfelter dip

Trainees' earnings were $20,000 two years before training, $15,000 the year before (after job losses) and $19,000 the year after. Comparison workers earned $20,000, $19,800 and $20,000. Compute DiD using the year before as baseline, then using two years before. Which is more credible?

Show solution

Step 1. Baseline = year before: treated +4,000+4{,}000; comparison +200+200; DiD =3,800= 3{,}800.

Step 2. Baseline = two years before: treated −1,000-1{,}000; comparison 00; DiD =−1,000= -1{,}000.

Step 3. The dip just before training is transitory: trainees enrolled because their earnings had temporarily fallen, and much of the rebound would have happened anyway.

Answer: the year-before baseline overstates the effect; analyses should use earlier baselines, model the dip, or compare with workers who had similar dips.

Verify in Python

import numpy as np

did = lambda t0, t1, c0, c1: (t1 - t0) - (c1 - c0)
print("Ex 1:", did(40, 52, 35, 41), " NJ:", round(did(20.44, 21.03, 23.33, 21.17), 2), " Medicaid:", did(320, 310, 330, 328))
print("logs vs levels:", did(20, 25, 10, 12), round(np.log(25 / 20) - np.log(12 / 10), 4))
print("bed nets placebo:", did(150, 140, 160, 155), " main:", did(140, 100, 155, 140))
print("Ashenfelter:", did(15_000, 19_000, 19_800, 20_000), did(20_000, 19_000, 20_000, 20_000))

# Regression form with simulated restaurants: the interaction equals the DiD of means
rng = np.random.default_rng(67)
n = 400; G = np.repeat([0, 1], n // 2)
y0 = 23 - 3 * G + rng.normal(0, 8, n)                      # before
y1 = y0 - 2 + 2.75 * G + rng.normal(0, 4, n)                # after: common trend -2, effect 2.75
Y = np.r_[y0, y1]; T = np.r_[np.zeros(n), np.ones(n)]; GG = np.r_[G, G]
X = np.column_stack([np.ones(2 * n), GG, T, GG * T])
b = np.linalg.lstsq(X, Y, rcond=None)[0]
means = did(y0[G == 1].mean(), y1[G == 1].mean(), y0[G == 0].mean(), y1[G == 0].mean())
fd = np.polyfit(G, y1 - y0, 1)[0]
print(f"interaction {b[3]:.3f}  DiD of means {means:.3f}  first-difference regression {fd:.3f}")

Key takeaways

  • DiD = (change for the treated) − (change for the comparison group); it identifies the ATT under parallel trends and no anticipation.
  • The regression interaction, the first-difference regression and the four-means formula are the same estimate.
  • Parallel trends is scale-dependent and fails with transitory pre-treatment shocks such as the Ashenfelter dip.

Simulation Lab: The 2×2 Difference-in-Differences

Open full screen →

Four means, a parallel counterfactual, and what levels-versus-logs and trend violations do to the estimate.

30405060beforeafteroutcomeDiD 6.0true Y(0)
DiD (levels)
6.00
true ATT
6.00
bias
0.00
DiD in logs
0.078
ATT in logs 0.111
treatedcomparisonDiD counterfactual (parallel)true untreated outcome

Mean outcomes before and after a policy for the treated group (blue) and a comparison group (grey). DiD assumes the treated group would have followed the dashed path, parallel to the comparison group in levels. Choose how the untreated world really evolves (parallel in levels or proportional growth) and add a violation to see the bias.

Day 66Day 68