Regression discontinuity, difference-in-differences and synthetic control
Before this lesson: lesson 02 (potential outcomes, ATT) and lesson 06 (the Wald ratio, needed for fuzzy RDD). Helpful: regression and its standard errors (probability 13) and linear regression in ML. Time: about 85 minutes, plus the notebook.
Why this matters #
- Thresholds of ML models. A fraud model blocks transactions with a score of at least 0.8; a credit model approves applicants above a score; a ranking puts items above a cutoff on the first page. Each rule is a regression discontinuity: it lets you estimate the effect of the action (blocking, approving, showing) near the threshold, without an experiment.
- Launches that cannot be randomized. A feature launched in one country, a price change in one region, a policy in one state. Difference-in-differences and synthetic control are the standard tools; Google's CausalImpact (Brodersen et al., 2015) is a Bayesian relative of synthetic control used for marketing.
- Economics and public health. Minimum wages (Card and Krueger, 1994), tobacco control (Abadie, Diamond and Hainmueller, 2010), class size (Angrist and Lavy, 1999), and thousands of policy evaluations use these designs.
1. Predict first #
2. The picture #
2.1 A jump at a cutoff #
Let be the running variable (the exam score) and the cutoff. In a sharp design, : everyone above the cutoff is treated, nobody below is. Plot the outcome against . If the scholarship has no effect, the cloud is smooth at . If it has an effect, the cloud jumps at . The size of the jump is the effect.
Why is this a fair comparison? Students with and are almost the same in everything: ability, effort, family. Only the treatment changes at . So near , the assignment is "as good as random". Far from the groups differ a lot, which is why we look only near .
To measure the jump, fit a line on each side using units close to , and read both lines at . The bandwidth says how close is close.
Move the bandwidth and switch the fit. Dots are units: blue treated (), orange control. The dashed aqua curves are the true regression functions; the thin dotted ones are the potential outcomes we never see on each side. The yellow window holds the units the local linear fit uses. Make large with curvature on: the lines miss the curve and the jump is biased. Make small: the jump gets noisy (press New sample). Try global degree 5 and press New sample a few times: the ends of the curves swing. Switch to fuzzy: the share treated jumps by only 0.5, and the effect is the ratio of the two jumps.
2.2 Two groups, two periods #
Now the treatment is a policy that starts at a known date in one group (the treated group) and not in another (the control group). The naive comparisons both fail:
- Before–after in the treated group mixes the effect with everything else that changed over time (the economy, the season).
- Treated vs control after the policy mixes the effect with the fixed differences between the groups.
Difference-in-differences (DiD) uses the control group's change over time as the counterfactual change for the treated group. Move the control line up or down until it starts at the treated group's level; where the treated group ends up above that moved line is the effect. This works if, without the policy, the two groups would have moved in parallel: the parallel-trends assumption.
Bend the trends and switch the view. Blue: treated group, orange: control group, policy from period 5 (shaded). The dashed dark line is the DiD counterfactual: the control line moved to the treated group's level before the policy. The dashed aqua line is the true of the treated group, which only a simulation can show. With trend violation 0 they agree. Set the violation to 0.2 from the start, then open event study: the coefficients before the policy slope away from 0, a warning you can see. Now choose only after the policy: the pre-period looks perfect, but the estimate is still biased.
Average sales per store: the treated region goes from 50 to 58 after a launch; the control region goes from 40 to 45 over the same time. What is the DiD estimate of the launch effect?
DiD . The value 8 is the before–after change of the treated region, which includes the common trend of +5. The value 13 is the post-launch difference , which includes the fixed gap of 10 between the regions.
3. Definitions and main results #
3.1 Sharp regression discontinuity #
Setting. Each unit has a running variable , observed before treatment. . Potential outcomes as in lesson 02.
Note what is unusual. At any value , all units are treated (if ) or all are controls. So positivity fails everywhere: we never see treated and control units with the same (lesson 05 needed both). RDD replaces positivity by a smoothness assumption and a limit.
Assumption (continuity). and are continuous in at .
In words: nothing other than the treatment changes suddenly at the cutoff. Without the scholarship, expected earnings would change smoothly with the exam score.
Theorem (identification of sharp RDD; Hahn, Todd and van der Klaauw, 2001). Under continuity and consistency,
Proof.
- For , every unit has , so by consistency and .
- For , every unit has , so .
- Take the limit from above in step 1. By continuity of at , the limit is .
- Take the limit from below in step 2. By continuity of at , the limit is .
- Subtract: the jump equals .
The effect is local. is the average effect for units at the cutoff. It says nothing direct about students with a score of 90 or 40. Extending it needs extra assumptions (for example, that the effect does not change with ).
3.2 Estimation: local linear regression and the bandwidth #
We need the two limits, which are values of regression functions at the boundary of their domains.
Local linear regression. On each side of , fit a line by weighted least squares, using only units with , with weights from a kernel. The common choice is the triangular kernel , which gives the most weight to units near the cutoff. The estimate is
Why a line and not just the mean of the nearby values? At a boundary, a local mean is biased by the slope of the regression function: the units on one side of all lie on one side of it. A local line removes this first-order bias (Fan and Gijbels, 1996).
Bias and variance in . A large uses many units (small variance) but includes units where the true function bends away from a line (large bias). A small has little bias and much variance. For a smooth function, the bias of local linear regression is of order and the variance of order . Data-driven bandwidths balance the two: Imbens and Kalyanaraman (2012) minimize the mean squared error of .
Robust bias-corrected inference
The MSE-optimal bandwidth leaves a bias of the same order as the standard error. So the usual interval
is centered in the wrong place and covers the truth less often than 95%.
Calonico, Cattaneo and Titiunik (2014) subtract an estimate of the bias (from a local quadratic fit) and
widen the standard error to include the uncertainty of that correction. This "robust bias-corrected"
interval is the default of the rdrobust software in R, Stata and Python.
Do not use high-order global polynomials. An old practice fits a polynomial of degree 3–5 in to all the data on each side. Gelman and Imbens (2019) give three reasons against it: the estimate puts large weights on units far from the cutoff, it is sensitive to the degree, and its confidence intervals are too short. Use local linear (or local quadratic) fits.
You increase the bandwidth from 0.1 to 1.0 in an RDD where the true regression function is curved. What happens to the local linear estimate?
A wider window uses more units, so the estimate is less noisy. But the line must now follow the curve over a long range, and its value at the cutoff moves away from the true limit. Section 5 shows it: with the estimate of a true jump of 1.0 is about 1.36.
3.3 Threats, checks and fuzzy RDD #
Continuity cannot be tested directly: it is a statement about potential outcomes at the cutoff. But it has testable consequences.
- Manipulation of the running variable. If students who score 69 can ask for a regrade, or retake the exam, the students just above 70 include the most persistent ones. Then the two sides differ by more than the treatment. The sign is bunching: too many units just above the cutoff. McCrary (2008) proposed a formal test of continuity of the density of at ; the notebook builds a simple version by counting units in bins next to the cutoff.
- Covariate continuity. Pre-treatment covariates (gender, past grades) must not jump at . Run the same RDD with each covariate as the outcome; the jumps should be near 0.
- Placebo cutoffs. Run the RDD at fake cutoffs (for example 60 or 80); there should be no jumps.
- Other rules at the same cutoff. If the score 70 also decides admission to a special class, the jump measures both treatments together.
Fuzzy RDD. Often the cutoff changes only the probability of treatment: above 70 you are eligible, but not everyone takes the scholarship, and some students below get it in other ways. Then jumps at by less than 1. The cutoff indicator is an instrument (lesson 06), used only near :
Under continuity, monotonicity (crossing the cutoff makes no one less likely to take the treatment) and exclusion (crossing the cutoff changes only through ), this is the average effect for compliers at the cutoff (Hahn, Todd and van der Klaauw, 2001): a LATE that is local twice. Estimate each jump with local linear regression, or run 2SLS with as instrument in the window.
At a cutoff, the share of treated units jumps from 0.30 to 0.70, and the mean outcome jumps by 2.0. What is the fuzzy RDD estimate?
The jump in treatment is . The fuzzy estimate is , the effect for compliers at the cutoff. The value 2.0 is the effect of crossing the cutoff (an intention-to-treat effect). The value divides by the wrong quantity.
3.4 Difference-in-differences #
Note on notation. In this lesson only, is time. We have a treated group () and a control group (), and two periods, "pre" and "post". The treated group is treated in the post period only. Potential outcomes now carry a time index: , , and so on.
The estimand is the effect on the treated in the post period: .
Assumptions.
- Parallel trends. Without treatment, the two groups would have changed by the same amount on average: .
- No anticipation. The treatment does not change the treated group's outcome before it starts: for the treated group.
- Consistency and no interference. In particular, the policy does not affect the control group (no spillovers), so the control group shows in both periods.
Parallel trends allows the groups to differ in levels: New Jersey stores can be smaller than Pennsylvania stores. It forbids differences in trends. It is an assumption about of the treated group, which is never observed.
Theorem (identification of DiD). Under assumptions 1–3,
Proof.
- The treated group is treated in the post period, so by consistency .
- By no anticipation, .
- The control group is never treated (and has no spillovers), so its observed change is .
- By parallel trends, replace that by .
- Put steps 1, 2 and 4 into the right side: . The two terms cancel, which leaves .
The regression form. With unit in period , for the treated group and in the post period,
The model has four parameters for four cell means, so OLS fits them exactly: is the control group's pre mean, the gap between the groups before, the control group's change, and the DiD. The regression form is useful because it extends: add covariates, more periods, unit fixed effects (one per unit) and period fixed effects (one per period).
Standard errors. Outcomes of the same unit (or state) are correlated over time. Treating every unit-period as independent makes the standard errors far too small (Bertrand, Duflo and Mullainathan, 2004). Cluster the standard errors at the level of the treatment assignment (unit, state). With very few clusters (for example, two states), even clustered standard errors are not reliable.
Which of these is the parallel-trends assumption of DiD?
Parallel trends is about the untreated potential outcome of the treated group, , after the policy: an unobserved counterfactual. Equal levels are not needed (DiD removes fixed gaps). Observed post-policy lines are not parallel when there is an effect. A constant effect is a different assumption.
3.5 Checking DiD: pre-trends and event studies #
With several periods before and after the policy (policy at period ), estimate one coefficient per period relative to the last pre-period:
This is an event study. Each is a small DiD between period and the reference period . Read the plot in two parts:
- Before the policy (): the test for pre-trends. If the groups already moved apart before the policy, parallel trends after it is hard to believe.
- After the policy (): the show how the effect changes over time (it may grow, or fade).
Flat pre-trends support parallel trends but do not prove it. The assumption is about the post-period, and a violation can start exactly with the policy (try only after the policy in the widget). Pre-trend tests also have low power: a real trend can hide in wide intervals, and choosing studies that "pass" the test can make the bias worse (Roth, 2022).
Two more checks. Placebo outcomes: an outcome the policy cannot affect should show no DiD effect. Scale: parallel trends in levels and in logs cannot both hold when the groups start at different levels and change over time. Choose the scale with a reason (for example, percent changes for growth processes) and say so.
3.6 Staggered adoption and two-way fixed effects #
Often units adopt the treatment at different times. The common regression is two-way fixed effects (TWFE): , with if unit is treated at time . When the effect is the same for all units and periods, is fine. When effects change over time, can be badly wrong.
Why TWFE fails with staggered timing, with a small example
Goodman-Bacon (2021) showed that the TWFE coefficient is a weighted average of all 2×2 DiD comparisons in the data. Some of them use already-treated units as controls. If the effect in those units is still changing, their change is not the counterfactual change, and the comparison is biased.
Example (verified in section 5). Two groups, three periods, untreated outcomes all 0 (so trends are exactly parallel). The early group is treated from period 2 with effects (period 2) and (period 3): the effect grows. The late group is treated from period 3 with effect . Every effect is positive; their average is .
| period 1 | period 2 | period 3 | |
|---|---|---|---|
| early group | 0 | 1 | 4 |
| late group | 0 | 0 | 1 |
The two 2×2 comparisons inside this table:
- Early vs late in periods 1–2 (the late group is not yet treated, a clean control): .
- Late vs early in periods 2–3 (the early group is already treated and serves as control): . The early group's growing effect () is subtracted as if it were a trend.
Here TWFE gives each comparison weight : . In terms of cell effects, : the cell "early group, period 3" gets weight . A negative weight on a positive effect turns the estimate negative.
What to do instead. Estimate each group-time effect , the effect in period for the group that adopted at time , by a clean 2×2 DiD against units that are never treated or not yet treated. Then average them with weights you choose (Callaway and Sant'Anna, 2021). Related estimators: Sun and Abraham (2021) for event studies, de Chaisemartin and D'Haultfœuille (2020).
Raise the growth of the effect and shrink the never-treated group. Each line is a group; a line is orange while its group is untreated and blue once it is treated. The grid below shows the weight TWFE gives to each treated group-period; magenta cells have negative weights. With growth 0, TWFE (magenta readout) equals the true average (aqua). With growth 2 and a small never-treated group, TWFE falls far below the truth and can turn negative, while the group-time average stays exact.
3.7 Synthetic control #
Sometimes only one unit is treated: California's 1988 tobacco-control program (Proposition 99), one country's launch. No single control unit is similar enough, and an average of all controls is not either. Synthetic control (Abadie, Diamond and Hainmueller, 2010) builds the comparison as a weighted average of donor units:
with weights chosen so that follows the treated unit's outcome closely in the pre-period (and matches pre-treatment predictors). The effect estimate in each post period is the gap .
- Why and ? The synthetic unit is then a convex combination of real units: no extrapolation outside the data, and the weights are easy to read ("40% Utah, 30% Nevada …"). The weights are usually sparse.
- When does it work? When the pre-period is long and the fit is close: a synthetic control that tracks the treated unit for many periods, through ups and downs, is likely to share its hidden drivers. When the pre-period fit is poor, do not trust the gap.
- Inference by placebos. There is only one treated unit, so the usual standard errors do not apply. Instead, apply the method to each donor as if it were treated (placebo in space) and compare the treated unit's gap with the placebo gaps, usually by the ratio of post- to pre-period root mean squared prediction error (RMSPE). In the tobacco study, California had the largest ratio of 39 states, a permutation p-value of , and the estimated drop in cigarette sales was about 26 packs per person per year by 2000.
Press Fit to the pre-period, then open placebo test. The blue line is the treated unit; the dark line is the synthetic control; the dashed aqua line is the treated unit's true . Donors with weight are yellow (thicker = more weight). With equal weights the synthetic line misses the pre-period, and the post-period gap is not the effect. After Fit it tracks the treated unit before period 20, and the gap after it is close to the true effect. In the placebo view, the treated unit's gap stands out among the donors' gaps.
3.8 Which design when? #
| Design | You need | It estimates | Key untestable assumption | Main checks |
|---|---|---|---|---|
| RDD | a rule with a cutoff on a running variable | effect at the cutoff (fuzzy: for compliers at the cutoff) | continuity of potential outcomes at | density (no bunching), covariate jumps, placebo cutoffs, bandwidth sensitivity |
| DiD | a policy change, a comparison group, pre-periods | ATT in the post-periods | parallel trends after the policy; no anticipation | event study (pre-trends), placebo outcomes, scale |
| Synthetic control | one or few treated units, many donors, a long pre-period | effect on the treated unit over time | the weighted donors follow the treated unit's after the policy | pre-period fit, placebo in space and in time, leave-one-donor-out |
| IV (lesson 06) | an as-if-random push on the treatment | LATE for compliers | exclusion | first stage, balance of |
Answers to section 1. (1) No. It estimates the effect for students near 70. Students with 95 also got the scholarship, but the design says nothing direct about them. (2) full-time-equivalent workers per store (the paper reports 2.76 from unrounded means). Employment did not fall in New Jersey relative to Pennsylvania. (3) No. Flat pre-trends support the assumption, but parallel trends is about the post-period, where the treated group's is never observed. A shock that starts with the policy cannot be seen in the pre-period.
4. Worked example #
(a) A sharp RDD by hand. The cutoff is . Near the cutoff the (noise-free) data are:
| 66 | 68 | 69 | 70 | 71 | 73 | |
|---|---|---|---|---|---|---|
| 58.0 | 59.0 | 59.5 | 63.0 | 63.5 | 64.5 |
Left of the cutoff, the points lie on a line with slope . Extend it to : . Right of the cutoff, the slope is , and the value at is . The jump is . Note that the left line must be extrapolated from 69 to 70: there are no untreated units at the cutoff. The naive comparison of the means of the two sides, , also counts the slope of in as an effect.
(b) Fuzzy RDD. Suppose only 70% of the students above 70 take the scholarship, and 30% of those below get it from other sources. The jump in at the cutoff is . If the jump in is , the effect for compliers at the cutoff is .
(c) DiD with the minimum-wage data. Card and Krueger (1994, Table 3) surveyed fast-food restaurants in New Jersey (treated: the minimum wage rose from $4.25 to $5.05 on 1 April 1992) and eastern Pennsylvania (control) before and after the rise. Mean full-time-equivalent (FTE) employment per store:
| before (Feb–Mar 1992) | after (Nov–Dec 1992) | change | |
|---|---|---|---|
| New Jersey (treated) | 20.44 | 21.03 | |
| Pennsylvania (control) | 23.33 | 21.17 | |
| difference NJ − PA |
- Before–after in New Jersey: . This mixes the effect with the regional trend.
- The Pennsylvania change, , estimates that trend (a weakening economy in 1992).
- DiD: . The paper reports (standard error ) from unrounded means.
- The same number from the other direction: the gap NJ − PA went from to , a change of .
- The regression form reproduces the table: (PA before), (NJ − PA before), (PA change), . Check one cell: NJ after ✓.
The estimate rests on parallel trends: without the law, New Jersey stores would have lost about 2.16 workers like Pennsylvania stores. With only two periods, this cannot be checked with pre-trends; the paper adds a within-New-Jersey comparison of low- and high-wage stores as a second control group.
(d) The TWFE example. In the table of section 3.6, the TWFE coefficient is , while every effect is positive and their average is 2. A group-time estimator with a never-treated group would recover each cell effect.
(e) A tiny synthetic control. Treated unit before the policy: . Donors: A and B . With , the synthetic unit is : a perfect pre-period fit. After the policy, the treated unit is 5, A is 6 and B is 8, so the synthetic value is , and the effect estimate is .
5. In code #
NumPy checks the numbers above. The notebook has these cells and the exercises.
import numpy as np
rng = np.random.default_rng(0)
# (a) sharp RDD: local linear regression with a triangular kernel on each side of c = 0
def rdd_local_linear(r, y, c=0.0, h=0.3):
ends = []
for side in (r < c, r >= c):
x, w = r[side] - c, np.clip(1 - np.abs(r[side] - c) / h, 0, None)
X = np.column_stack([np.ones_like(x), x]) * np.sqrt(w)[:, None]
ends.append(np.linalg.lstsq(X, y[side] * np.sqrt(w), rcond=None)[0][0]) # value at the cutoff
return ends[1] - ends[0]
n = 5_000
r = rng.uniform(-1, 1, n)
y = 1 + 0.5 * r + 0.6 * np.sin(3 * r) + 1.0 * (r >= 0) + 0.4 * rng.normal(size=n) # true jump 1.0
for h in (0.1, 0.3, 1.0):
print(f"h = {h}: jump {rdd_local_linear(r, y, h=h):.3f}")
# h = 0.1: jump 0.980
# h = 0.3: jump 0.962
# h = 1.0: jump 1.364
# (b) DiD from four means (Card and Krueger 1994, Table 3, FTE employment per store)
nj_pre, nj_post, pa_pre, pa_post = 20.44, 21.03, 23.33, 21.17
print(f"DiD = ({nj_post} - {nj_pre}) - ({pa_post} - {pa_pre}) = {(nj_post - nj_pre) - (pa_post - pa_pre):.2f}")
# DiD = (21.03 - 20.44) - (21.17 - 23.33) = 2.75
# (c) TWFE with staggered adoption: 2 groups, 3 periods, all effects positive
# early group treated from t = 2 (effects 1 at t = 2, 4 at t = 3); late group from t = 3 (effect 1)
Y = np.array([[0., 1, 4], # early group: Y(0) = 0, plus the effects
[0., 0, 1]]) # late group
D = np.array([[0, 1, 1], [0, 0, 1]])
g, t = np.meshgrid(range(2), range(3), indexing="ij")
X = np.column_stack([D.ravel(), g.ravel() == 1, t.ravel() == 1, t.ravel() == 2, np.ones(6)]).astype(float)
print(f"TWFE coefficient: {np.linalg.lstsq(X, Y.ravel(), rcond=None)[0][0]:.2f}")
# TWFE coefficient: -0.50
In (a), the bandwidth uses all the data, and the curvature of biases the jump by about 0.36. In (c), the regression has a dummy for the late group, dummies for periods 2 and 3 and a constant: exactly TWFE.
6. Where it shows up #
- Decision thresholds in ML systems. Any action triggered by a model score above a threshold (block, review, approve, show a warning) creates a sharp or fuzzy RDD. It is a cheap way to measure the effect of the action near the threshold, without an A/B test. Watch for manipulation: users and fraudsters learn thresholds.
- Product launches by region or by date. DiD with an event study is the standard analysis when a feature launches in some markets first. With rollouts in waves, use group-time estimators, not TWFE.
- Marketing measurement. Geo experiments and synthetic-control-style methods (CausalImpact; augmented and penalized synthetic control) estimate the effect of a campaign in one region.
- Policy and health. Minimum wages, tobacco taxes, Medicaid expansions (staggered across US states), school-entry age cutoffs, test-score cutoffs for schools, and age-65 eligibility for Medicare are classic natural experiments.
- ML for science. Climate and environmental policy studies (for example, the effect of a regulation on air quality in some regions) often use DiD and synthetic control with satellite or sensor data.
7. Common mistakes #
- Reading an RDD effect as the effect for everyone. It holds at the cutoff (fuzzy: for compliers at the cutoff). Say so.
- Fitting high-order global polynomials. Use local linear regression with a data-driven bandwidth, and show that the result is stable for nearby bandwidths.
- Ignoring manipulation. Plot the histogram of the running variable. Bunching just above the cutoff breaks the design.
- Taking flat pre-trends as proof. They support parallel trends but cannot test the post-period. Argue why nothing else changed at the same time.
- Using TWFE with staggered adoption and changing effects. Already-treated units become controls; weights can be negative. Use group-time estimators and plot their event study.
- Unclustered standard errors in panels. Serial correlation makes naive standard errors far too small. Cluster at the level of treatment assignment.
- Spillovers to the control group. If the policy also affects the control units (workers move across the border), the control change is not , and DiD is biased.
- Trusting a synthetic control with a poor pre-period fit. If the synthetic line cannot follow the treated unit before the policy, the post-period gap is not an effect estimate.
8. Check yourself #
- State the continuity assumption of a sharp RDD and say why it is needed.
Answer
and are continuous at . It is needed because no untreated units exist at or above : we learn only as the limit from below, which equals the value at only if the function has no jump there. - A bank approves loans for credit scores of at least 650. Applicants with 649 can apply again a week later after paying off a small debt. Which RDD check would show this, and what would it show?
Answer
The density (McCrary-type) check: a histogram of scores would show too few applicants just below 650 and too many just above it (bunching). The applicants who reapply may differ (more motivated), so continuity is in doubt. - In a fuzzy RDD, the cutoff raises the share treated by 0.25 and the mean outcome by 0.5. What is the estimate, and for whom?
Answer
: the average effect for compliers at the cutoff (units who take the treatment because they cross the cutoff), under continuity, monotonicity and exclusion. - Write the DiD regression and say what each coefficient means.
Answer
. : control mean before; : treated minus control before; : control change; : the DiD, the ATT under parallel trends and no anticipation. - An event study shows pre-period coefficients for periods (reference ). What do you conclude?
Answer
The treated group was already rising relative to the control group before the policy, by about 0.3 per period. Parallel trends is not plausible; the DiD estimate would include this trend. Consider other control groups, a design with group-specific trends (with care), or another design. - Why must synthetic-control weights be non-negative and sum to 1?
Answer
Then the synthetic unit is a convex combination of real donors: it stays within the range of the data (no extrapolation) and is interpretable. With free regression weights, a good pre-period fit can come from over-fitting with large positive and negative weights.
What is the estimand of a sharp regression discontinuity design?
, the average effect for units at the cutoff, identified as the jump in at .
What is the continuity assumption of RDD?
and are continuous at : nothing other than the treatment jumps at the cutoff.
Why use local linear regression and not high-order global polynomials in RDD?
Local linear fits have small boundary bias and use units near the cutoff; global high-order polynomials give large weights to far units, depend on the degree and have too-short intervals.
What does a density (McCrary) test check in an RDD?
Whether units bunch just above (or below) the cutoff, a sign that they manipulate the running variable, which breaks continuity.
Compute a fuzzy RDD estimate when jumps by 0.4 and the outcome jumps by 2.0.
, the effect for compliers at the cutoff.
State the parallel-trends assumption.
Without treatment, the treated group's average outcome would have changed by the same amount as the control group's: .
Compute DiD for treated and control .
.
What is an event study used for in DiD?
To estimate one effect per period relative to a reference period: pre-period coefficients check for pre-trends, post-period coefficients show how the effect evolves.
Why can TWFE fail with staggered adoption?
It uses already-treated units as controls; when their effects change over time, some treated cells get negative weights and the estimate can even have the wrong sign.
What is a synthetic control?
A weighted average of untreated donor units (, ) that tracks the treated unit before the policy; the post-period gap estimates the effect.
9. Interview angle #
- "We launched a feature in one country only. How do you measure its effect?" — With a few comparable countries and many pre-launch weeks: DiD with an event study (check pre-trends, cluster by country), or synthetic control if no single country is comparable (check the pre-period fit, run placebos). Discuss what else changed at launch time (holidays, marketing) and spillovers (users who travel).
- "A fraud model blocks transactions with score ≥ 0.8. How do you estimate the effect of blocking on later customer churn?" — RDD at 0.8: compare customers just above and just below with local linear regression. If some blocked transactions are released by manual review, it is a fuzzy RDD: divide by the jump in the blocking rate. Check that the score cannot be manipulated and that nothing else uses the same threshold. The answer holds for scores near 0.8 only.
- "What is the parallel-trends assumption and how do you check it?" — State it in terms of ; check pre-trends with an event study and placebo outcomes; say that the post-period part is untestable.
- "Why not just run TWFE on the rollout data?" — With staggered rollout and effects that grow, TWFE compares new adopters with earlier adopters and can be biased, even in sign. Use group-time estimators.
10. Practice #
The notebook for this lesson has five exercises, each with a check cell and a folded solution:
rdd_local_linear(r, y, c, h)with a triangular kernel; a bandwidth sweep shows bias and variance.density_check(r, c, width): detect bunching created by manipulation of the running variable.did_2x2,did_regressionandevent_study: the same DiD three ways, with visible and invisible trend violations.twfevsgroup_time_attunder staggered adoption with growing effects.synthetic_controlby projected gradient descent onto the simplex, then a placebo-in-space test.
11. Watch and read #
- Scott Cunningham, Causal Inference: The Mixtape (free online): ch. 6 Regression Discontinuity, ch. 9 Difference-in-Differences, ch. 10 Complex Diff-in-Diff Designs (staggered adoption), ch. 11 Synthetic Control.
- Nick Huntington-Klein, The Effect (free online): ch. 18 Difference-in-Differences, ch. 20 Regression Discontinuity.
- Card and Krueger (1994), Minimum Wages and Employment: A Case Study of the Fast-Food Industry in New Jersey and Pennsylvania, American Economic Review (author's PDF; Table 3 has the numbers of section 4).
- Gelman and Imbens (2019), Why High-Order Polynomials Should Not Be Used in Regression Discontinuity Designs (NBER working paper).
- Goodman-Bacon (2021), Difference-in-Differences with Variation in Treatment Timing (NBER working paper), and Callaway and Sant'Anna (2021), Difference-in-Differences with Multiple Time Periods (arXiv).
- Abadie, Diamond and Hainmueller (2010), "Synthetic Control Methods for Comparative Case Studies: Estimating the Effect of California's Tobacco Control Program", JASA.
Runs in your browser with nothing to install. The notebook repeats the key demos and has exercises with checks; solutions are inside, folded.
No Google account needed: Python runs inside your browser. The first start downloads about 40 MB; your changes are saved in this browser only.