Day 70. Staggered Adoption: the Goodman-Bacon Decomposition
When units adopt a policy at different times, the TWFE coefficient is a weighted average of every possible 2×2 DiD, including comparisons that use already-treated units as controls. With effects that change over time those comparisons are contaminated, and TWFE can be far from, or even opposite in sign to, every true effect.
- ●List the 2×2 comparisons hidden inside a staggered TWFE regression.
- ●Explain the decomposition weights and why units treated in the middle of the panel get the most weight.
- ●Prove that TWFE is unbiased with constant effects and biased with dynamic effects through "forbidden" comparisons.
- ●Compute a decomposition and compare TWFE with the true average effect.
Theory
Staggered adoption
Units adopt treatment at different dates and stay treated. Write for an early group (adopts at ), for a late group (), and for never-treated units. The common practice was to run the TWFE regression and call "the effect".
The decomposition
Goodman-Bacon (2021) showed that, in a balanced panel,
With one early group, one late group and a never-treated group there are four comparisons:
| Comparison | Treated | Control | Window |
|---|---|---|---|
| early | never | all periods | |
| late | never | all periods | |
| early | late (not yet treated) | before | |
| late | early (already treated) | from on |
The weights
Each weight grows with the size of the two groups and with the variance of treatment in the comparison, , where is the share of the window in which the treated group is treated. Groups treated in the middle of the panel ( near 0.5) get the most weight; this weighting is a property of OLS, not of the policy question.
When it goes wrong
- Constant effects: every 2×2 equals the effect; TWFE is fine.
- Effects differing across groups but constant over time: TWFE is a convex, variance-weighted average of group effects; not the ATT, but between them.
- Effects that change over time: the comparison uses the early group as a control after it was treated, so its still-evolving effect is subtracted. TWFE can be biased and even have the wrong sign. In the equivalent ATT language (de Chaisemartin and D'Haultfœuille), some group-time effects receive negative weights.
Diagnostics and fixes
Plot the 2×2 estimates against their weights (a "Bacon plot"), check how much weight falls on already-treated controls, and use heterogeneity-robust estimators that never use treated units as controls (Day 71).
Part 1 · Warm-up
Exercise 1 · Count the comparisons
With an early group, a late group and never-treated units, list the 2×2 comparisons. How many are there with three timing groups and a never-treated group?
Show solution
Step 1. Two groups: each timing group against never-treated (2), and each ordered pair of timing groups with the later or earlier one as control (2). Total 4.
Step 2. Three timing groups: 3 against never-treated, plus 2 for each of the 3 pairs = 6. Total 9 ( with timing groups).
Exercise 2 · Treatment variance
In a 10-period panel, the early group is treated from period 4, the late group from period 7. Compute for each against the never-treated group.
Show solution
Step 1. Early: treated 7 of 10 periods, , variance .
Step 2. Late: treated 4 of 10, , variance .
Answer: the late group's comparison gets slightly more weight per unit, being closer to the middle of the panel.
Exercise 3 · Constant effects
If treatment raises outcomes by exactly 2 for every unit in every treated period, what does each 2×2 estimate and TWFE equal?
Show solution
Step 1. Each 2×2 compares changes; untreated trends are parallel and every post-period difference is 2.
Answer: every comparison equals 2, so TWFE = 2 whatever the weights.
Exercise 4 · The forbidden comparison
Explain why the late-versus-early comparison is problematic when the early group's effect grows over time.
Show solution
Step 1. In the window from , the early group is always treated, so it serves as the "control".
Step 2. Its outcomes keep changing because its treatment effect keeps growing, not because of a common trend.
Answer: that growth is subtracted from the late group's change, biasing the comparison downward.
Exercise 5 · Which units identify what?
In the 2×2 that compares early with late before , why is the late group a legitimate control?
Show solution
Step 1. Before , the late group is untreated: its changes reflect untreated trends.
Answer: under parallel trends (and no anticipation by the late group), it is a valid "not-yet-treated" control.
Part 2 · Proofs
Exercise 6 · Constant effects mean no bias
Assume parallel trends and a constant effect for all units and periods. Prove each 2×2 estimand equals , and hence .
Show solution
Step 1. In any 2×2, the treated group's change is (common trend) + × (change in its treatment status between pre and post windows) = trend + .
Step 2. The control group's change is the common trend: for not-yet-treated controls nothing changes; for already-treated controls the effect is present in both windows and cancels.
Step 3. Each 2×2 equals ; the weights sum to 1.
Exercise 7 · The contaminated comparison
Let the early group's effect be at event time and the late group's . Show that, under parallel trends, , where the bars average over the windows' periods.
Show solution
Step 1. Late group: its change between the window's pre part (, untreated) and post part () is trend + average over the post part.
Step 2. Early group: treated throughout; its change is trend + (average in the post part − average in the pre part).
Step 3. Subtract. If grows over time, the bracket is positive and the comparison is biased downwards.
Exercise 8 · Group-specific constant effects
Suppose effects differ across groups but not over time (, ). Show , a convex combination that generally differs from the ATT.
Show solution
Step 1. , , (late group untreated in that window).
Step 2. By Exercise 7 with constant , the bracket is 0, so .
Step 3. Collect terms; weights are non-negative and sum to 1. The ATT weights groups by their number of treated unit-periods instead.
Exercise 9 · A wrong sign
Construct an example (early effect growing, late effect small) in which although every unit's effect is non-negative.
Show solution
Step 1. Let (zero on impact, growing by 1 per period) and .
Step 2. With the early group adopting at period 4 and the late at 7 in a 10-period panel, the window pre part is periods 4–6 (; mean 1) and post part 7–10 (; mean 4.5).
Step 3. By Exercise 7: .
Answer: a negative comparison from non-negative effects; with enough weight it can make TWFE negative.
Exercise 10 · Weights favour the middle
For a timing group compared with never-treated units of equal size, the weight is proportional to . Show this is maximised when treatment covers half the panel.
Show solution
Step 1. has derivative .
Step 2. Zero at ; second derivative . Groups adopting near the start or end of the panel get little weight, regardless of how policy-relevant they are.
Part 3 · Applied
Exercise 11 · Divorce law reforms with dynamic effects
States adopt a reform in period 4 (early) or 7 (late) of a 10-period panel; a third of states never adopt; groups are equal in size. Effects grow: 1 on impact, +0.5 per year. The 2×2 estimates are 2.5 (early vs never), 1.75 (late vs never), 1.5 (early vs not-yet-treated late) and 0 (late vs already-treated early), with weights 0.318, 0.364, 0.136, 0.182. Compute TWFE and compare with the ATT over all treated state-years.
Show solution
Step 1. .
Step 2. ATT: early cells (periods 4–10, ) average ; late cells (7–10, ) average .
Step 3. Weighted by treated cells: .
Answer: TWFE (1.64) understates the ATT (2.23) by about a quarter; the forbidden comparison contributes 0 with 18% weight.
Exercise 12 · Changing the group sizes
Repeat Exercise 11 with group sizes 2 (early) : 1 (late) : 3 (never), which give weights 0.525, 0.300, 0.075, 0.100. Compute TWFE.
Show solution
Step 1. .
Answer: 1.95, against an ATT of 2.33 with these group sizes: more never-treated units shift weight to clean comparisons, but bias remains.
Exercise 13 · Diagnosing a published estimate
A paper's TWFE estimate of a hospital-merger effect on prices is 1%; a Bacon decomposition shows 40% of the weight on comparisons with already-merged hospitals as controls, whose 2×2 estimates are −4%. What would you conclude?
Show solution
Step 1. The clean comparisons must average about .
Step 2. The negative forbidden comparisons pull TWFE down, consistent with price effects that grow after mergers.
Answer: the true effect is likely several times larger than 1%; re-estimate with a heterogeneity-robust method (Day 71).
Exercise 14 · Electronic health records
Hospitals adopted electronic health records between 2008 and 2016, with incentives starting in 2011; almost all had adopted by 2016. A study wants the effect on medication errors. What design concerns does staggered adoption raise?
Show solution
Step 1. Few never-treated hospitals: most comparisons in TWFE would use earlier adopters as controls for later ones.
Step 2. Learning effects make the impact grow over time, the case where those comparisons are biased.
Step 3. Better: group-time ATTs with not-yet-treated controls, restricted to periods before almost everyone adopted, and event-study plots by cohort.
Exercise 15 · What to report
List what a staggered-adoption DiD paper should report alongside (or instead of) a single TWFE coefficient.
Show solution
Step 1. The adoption timeline (how many units adopt when; any never-treated units).
Step 2. A Bacon decomposition: estimates and weights by comparison type.
Step 3. Heterogeneity-robust estimates (group-time ATTs and event-study aggregations) and their pre-trends.
Step 4. A discussion of which average effect is reported and for which units.
Verify in Python
import numpy as np
def panel(T, tk, tl, eff, eff_late=None):
eff_late = eff_late or eff
t = np.arange(1, T + 1)
D = np.array([(t >= tk), (t >= tl), np.zeros(T, bool)]).astype(float)
base = np.array([1.0, 2.0, 0.5])[:, None] + 0.3 * t[None, :]
E = np.array([eff(t - tk), eff_late(t - tl), np.zeros(T)])
return base + D * E, D, t
def twfe_weighted(Y, D, w):
w = w / w.sum()
dm = lambda M: M - M.mean(1, keepdims=True) - (w[:, None] * M).sum(0) + (w[:, None] * M.mean(1, keepdims=True)).sum()
Dd = dm(D)
return (w[:, None] * Dd * Y).sum() / (w[:, None] * Dd ** 2).sum()
def bacon(Y, t, tk, tl, w):
did = lambda a, b, pre, post: (Y[a, post].mean() - Y[a, pre].mean()) - (Y[b, post].mean() - Y[b, pre].mean())
pk, pl = t >= tk, t >= tl
b = np.array([did(0, 2, ~pk, pk), did(1, 2, ~pl, pl), did(0, 1, ~pk & ~pl, pk & ~pl), did(1, 0, pk & ~pl, pl)])
nk, nl, nu = w / w.sum(); Dk, Dl = pk.mean(), pl.mean()
sh = lambda a, c: a / (a + c)
s = np.array([(nk + nu) ** 2 * sh(nk, nu) * (1 - sh(nk, nu)) * Dk * (1 - Dk),
(nl + nu) ** 2 * sh(nl, nu) * (1 - sh(nl, nu)) * Dl * (1 - Dl),
((nk + nl) * (1 - Dl)) ** 2 * sh(nk, nl) * (1 - sh(nk, nl)) * (Dk - Dl) / (1 - Dl) * (1 - Dk) / (1 - Dl),
((nk + nl) * Dk) ** 2 * sh(nk, nl) * (1 - sh(nk, nl)) * Dl / Dk * (Dk - Dl) / Dk])
return b, s / s.sum()
for label, eff in [("constant effect 2", lambda e: 2 + 0 * e), ("dynamic 1 + 0.5e", lambda e: 1 + .5 * e)]:
for w in (np.array([1., 1, 1]), np.array([2., 1, 3])):
Y, D, t = panel(10, 4, 7, eff)
b, s = bacon(Y, t, 4, 7, w)
att = (w[0] * eff(np.arange(7)).sum() + w[1] * eff(np.arange(4)).sum()) / (7 * w[0] + 4 * w[1])
print(f"{label:18s} sizes {w.astype(int)}: 2x2s {b.round(2)} weights {s.round(3)} "
f"sum {(s * b).sum():.3f} TWFE {twfe_weighted(Y, D, w):.3f} ATT {att:.3f}")
# Exercise 9: early effect = e (growing), late effect = 0.5
Y, D, t = panel(10, 4, 7, lambda e: e * 1.0, lambda e: 0.5 + 0 * e)
b, s = bacon(Y, t, 4, 7, np.ones(3))
print("late vs already-treated early:", round(b[3], 2))
Key takeaways
- Staggered TWFE averages all 2×2 DiDs, with OLS weights that favour groups treated mid-panel.
- Comparisons that use already-treated units as controls subtract their evolving effects; with dynamic effects TWFE is biased and can flip sign.
- Report the adoption pattern and a decomposition, and use estimators that only compare with not-yet- or never-treated units.
Simulation Lab: The Goodman-Bacon Decomposition
Open full screen →Staggered adoption as four weighted 2×2 DiDs, including the forbidden comparison with already-treated units.
Three groups: early adopters, late adopters and never-treated, with a common trend. The TWFE coefficient equals the weighted sum of four 2×2 DiDs (bar heights; bar widths are the weights). With effects that grow over time, the comparison that uses already-treated early adopters as controls is biased, and TWFE drifts away from the average effect on treated unit-periods.