- Difference-in-differences (DiD) estimates the effect of a policy by comparing how much the outcome changed in a treated group with how much it changed in an untreated control group over the same period.
- It is literally two differences: DiD = (treated after − treated before) − (control after − control before).
- The same number comes from one regression: the coefficient on treated × post.
- Worked example: a minimum-wage rise in one state. Treated restaurants gained 0.905 FTE workers while control restaurants lost 1.846, so DiD = +2.751 FTE (clustered s.e. 0.493).
- Everything rests on parallel trends: without the policy, both groups would have changed by the same amount. You cannot test it directly, but you can make it believable.
Difference-in-differences is the workhorse method for measuring what a policy actually did when nobody ran an experiment. A state raises its minimum wage, a city adds a congestion charge, a school district changes its curriculum: in each case some units are treated and others are not, and you can see both groups before and after. This guide explains difference-in-differences from scratch, works through a full example with real software output, and answers the questions students most often ask about it, from the parallel trends assumption to clustered standard errors and staggered adoption.
The problem DiD solves
Suppose a state raises its minimum wage and you want to know what happened to employment in fast-food restaurants. There are two obvious comparisons, and both are wrong.
Before versus after in the treated state. Employment may have changed for reasons that have nothing to do with the minimum wage: a regional recession, a rise in food costs, a change in the season. A before–after comparison credits the policy with all of it.
Treated versus control after the policy. The two states may have differed before the policy. Perhaps restaurants in the treated state were always smaller. A comparison of levels after the policy mixes up that old gap with the effect.
Difference-in-differences combines the two so that each fixes the other’s weakness. Taking changes within each group removes any fixed gap between them; subtracting the control group’s change removes the common time effect.[1]
The full development, with the potential-outcomes framework, randomised trials and regression discontinuity alongside DiD, is in Chapter 16 of the Econometrics Made Simple textbook. The worked example below uses that chapter’s dataset.
The worked example: a minimum-wage rise
The file minwage_did.csv from Econometrics Made Simple, Chapter 16, records full-time-equivalent employment (fte) at 400 fast-food restaurants: 220 in a state that raised its minimum wage (treated = 1) and 180 in a neighbouring state that did not. Each restaurant is observed once before the rise and once after it (post = 0, 1), so there are 800 rows. Each restaurant belongs to one of four chains. The data are simulated in the spirit of Card and Krueger’s famous New Jersey–Pennsylvania study,[2] so their numbers are not Card and Krueger’s. The advantage is that we know the truth: an effect of +2.6 FTE was built into the data.
Step 1: the 2 × 2 table of means
Every DiD starts with four averages: each group, before and after.
| Before | After | Change | |
|---|---|---|---|
| Treated state (220 restaurants) | 17.998 | 18.902 | +0.905 |
| Control state (180 restaurants) | 19.540 | 17.694 | −1.846 |
| Treated − control | −1.542 | +1.208 | +2.751 |
Changes and the DiD are computed from unrounded means, so the last digit can differ by one from subtracting the rounded figures.
Compute the difference-in-differences estimate from the table and say what each step removes.
Notice how badly the naive comparisons do. Before–after in the treated state says +0.905; treated–control after the policy says +1.208. The true effect in the simulation is +2.6, and only DiD gets close.
Step 2: the counterfactual picture
Figure 1 shows what DiD assumes. Without the policy, the treated state would have followed the dashed line, parallel to the control state’s fall of 1.846, and ended at \( 17.998-1.846 = 16.152 \). It actually ended at 18.902. The vertical gap, \( 18.902-16.152 = 2.750 \), is the estimated effect. Relative to the counterfactual it is about 17%.
The difference-in-differences regression
The table gives no standard error. The regression form does, and it extends to controls and to many groups and periods.
Plug in the four combinations of the two dummy variables and you get the four cell means:
| post = 0 | post = 1 | Change | |
|---|---|---|---|
| treated = 0 | \( \beta_0 \) | \( \beta_0 + \beta_2 \) | \( \beta_2 \) |
| treated = 1 | \( \beta_0 + \beta_1 \) | \( \beta_0 + \beta_1 + \beta_2 + \beta_3 \) | \( \beta_2 + \beta_3 \) |
So \( \beta_1 \) is the gap that existed before the policy, \( \beta_2 \) is the change over time common to both groups, and the interaction coefficient \( \beta_3 \) is the difference-in-differences. If you need a refresher on how dummy variables and interactions shift a regression line, see our guide to dummy variables.
import pandas as pd
import statsmodels.formula.api as smf
d = pd.read_csv("minwage_did.csv")
# DiD regression, standard errors clustered by restaurant
m = smf.ols("fte ~ treated + post + treated:post", data=d).fit(
cov_type="cluster", cov_kwds={"groups": d["store"]})
print(m.summary().tables[1])
The output, from Econometrics Made Simple, Chapter 16:
| Term | Coefficient | Clustered s.e. | z | 95% CI |
|---|---|---|---|---|
| Intercept (\( \beta_0 \)) | 19.540 | 0.498 | 39.24 | [18.564, 20.516] |
| treated (\( \beta_1 \)) | −1.542 | 0.684 | −2.25 | [−2.883, −0.201] |
| post (\( \beta_2 \)) | −1.846 | 0.394 | −4.69 | [−2.617, −1.075] |
| treated × post (\( \beta_3 \)) | 2.751 | 0.493 | 5.58 | [1.784, 3.717] |
The coefficients reproduce the table exactly: 19.540 is control-before, −1.542 the initial gap, −1.846 the common change, and 2.751 the DiD. The interaction is highly significant (\( z = 2.751/0.493 = 5.58 \)), and the 95% confidence interval [1.78, 3.72] contains the true value of 2.6. For a reminder of how to read each column, see how to read regression output.
library(sandwich); library(lmtest)
d <- read.csv("minwage_did.csv")
m <- lm(fte ~ treated * post + factor(chain), data = d)
coeftest(m, vcov = vcovCL(m, cluster = ~store)) # treated:post = 2.751, s.e. 0.494
import delimited using "minwage_did.csv", clear
encode chain, generate(chain_id)
regress fte i.treated##i.post i.chain_id, vce(cluster store)
xtset store post
xtreg fte i.treated##i.post, fe vce(cluster store) // store fixed effects
In R, treated * post expands to both main effects plus the interaction; in Stata, i.treated##i.post does the same.
Adding control variables
Adding chain dummies leaves the estimate at 2.751 (s.e. 0.494). That is not a coincidence. Each restaurant stays in the same chain in both periods, so chain cannot explain any part of the change in employment. Controls matter in DiD when the mix of units changes between periods (a repeated cross-section rather than a panel), or when you let them have their own trends. Allowing each chain its own change over time (chain × post) moves the estimate only slightly, to 2.729 (s.e. 0.498).
Be careful about which controls you add. A variable measured after the policy that the policy itself could have changed, such as the restaurant’s wage bill, is a “bad control”: holding it fixed blocks part of the effect you want to measure. Use characteristics fixed before the treatment, or let them enter as interactions with post.[3]
DiD and fixed effects
You can go further and give every restaurant its own intercept: store fixed effects. With two periods, store fixed effects are exactly the same as first differences: regress each restaurant’s change in employment, \( \Delta \text{fte}_i \), on treated. The answer is again 2.751 (s.e. 0.493). So DiD is a special case of a two-way fixed effects regression, with unit effects and time effects plus the treatment dummy. That connection is why panel methods and DiD are usually taught together; our guide to fixed effects vs random effects covers the panel side.
Clustered standard errors
The 800 rows are not 800 independent observations. They are 400 restaurants observed twice, and a restaurant that is large before the rise is large after it, so its two errors are correlated. Standard errors should be clustered by restaurant.
Here the usual OLS standard error on the interaction is 0.977 while the clustered one is 0.493. Clustering usually raises standard errors; here it halves them. The persistent size of each restaurant appears in both its observations and cancels out of the DiD comparison, but the usual formula treats it as fresh noise each time. Whichever way it goes, clustering gets it right. With many periods the danger runs the other way: Bertrand, Duflo and Mullainathan showed that DiD studies with long panels and serially correlated outcomes that ignore clustering reject true null hypotheses far too often.[4]
treated or on post as “the effect”. \( \beta_1 \) is the pre-existing gap between the groups and \( \beta_2 \) is the common time trend. Only the interaction \( \beta_3 \) is the DiD estimate.The parallel trends assumption
DiD uses the control group’s change as the counterfactual for the treated group. In potential-outcomes notation, where \( Y(0) \) is the outcome a unit would have had without treatment, it assumes
Two things follow. The groups do not need to be similar in level: our treated restaurants started 1.542 FTE smaller, and DiD handles that easily. And because the assumption concerns a counterfactual, it can never be tested directly. You can only make it believable.
How to check parallel trends
- Plot the pre-treatment trends. With several periods before the policy, plot the two groups’ means. If they moved together for years before the policy, it is believable that they would have continued to. Our dataset has only one “before” period, so this check is impossible, which is a real weakness of any two-period DiD.
- Run an event study. Replace the single interaction with one interaction per period, relative to the policy date, leaving out the period just before it. The coefficients on the leads (periods before the policy) should be close to zero, since the policy cannot act before it happens.
- Run placebo tests. Pretend the policy happened a year earlier and use only pre-policy data, or use an outcome the policy cannot affect. The “effect” should be zero.
- Check that the policy bit. If the minimum wage rose, starting wages in the treated state should rise. In our data a DiD for
wage_startgives +$0.450 an hour (clustered s.e. 0.034): treated restaurants’ average starting wage rose from $4.60 to $5.08 while control restaurants’ barely moved ($4.60 to $4.63). The policy clearly reached the restaurants. - Choose a similar control group. Neighbouring regions exposed to the same weather, customers and regional economy are more likely to share trends than distant ones. That is why Card and Krueger compared New Jersey with neighbouring eastern Pennsylvania.[2]
Threats to a DiD design
Different underlying trends. If the treated state’s economy was already growing faster, DiD credits the policy with that growth.
Other changes at the same time. If the treated state also cut business taxes that year, DiD measures the combined effect.
Ashenfelter’s dip. People often join training programmes after a bad spell, so their earnings dip just before treatment and recover afterwards regardless. Using the dip year as “before” flatters the programme.[6] Governments also tend to act because an outcome has recently been unusually bad.
Anticipation and spillovers. If firms cut hiring as soon as the rise was announced, the “before” period is already affected. If workers commute across the border to the better-paid jobs, the control group is affected too.
Changing composition. If restaurants open or close because of the policy, the restaurants observed after differ from those observed before. Following the same units, as in our panel, helps.
Does the effect differ between groups?
Figure 2 runs the DiD separately for each chain. BurgerCo’s estimate (1.08) looks lower, but its standard error is 1.15, so its interval easily contains the pooled 2.75. With roughly 100 restaurants per chain, the data cannot show that the effect differs between chains. That is the right conclusion: the data were simulated with the same effect everywhere. Test such differences formally (for example with a triple interaction) rather than by eye.
More periods and staggered adoption
Real policy data rarely come as a tidy 2 × 2. With many periods and a single policy date, the event study mentioned above is the standard tool. Its post-policy coefficients show whether the effect builds up or fades, and its leads check pre-trends.
Things get harder when different units adopt the policy at different dates (staggered adoption), for example when states raise minimum wages in different years. The usual two-way fixed effects regression, \( y_{it} = \alpha_i + \lambda_t + \delta D_{it} + u_{it} \), then produces a weighted average of many 2 × 2 comparisons. Goodman-Bacon (2021) shows that some of those comparisons use already-treated units as controls, and when effects change over time some weights can even be negative, so \( \hat{\delta} \) can be misleading.[7] Newer estimators, such as those of Callaway and Sant’Anna (2021), compare each adoption cohort only with units not yet treated and then average the results.[8] If your project has staggered timing, use one of these and report it alongside the two-way fixed effects estimate.
When should you use DiD?
| Method | What it needs | Key assumption |
|---|---|---|
| Randomised trial | You control who is treated | Random assignment |
| Difference-in-differences | Treated and control groups, before and after | Parallel trends |
| Regression discontinuity | Treatment set by a cut-off in a score | No other jump at the cut-off |
| Instrumental variables | A variable that shifts treatment but not the outcome directly | Relevance and exclusion |
| Fixed effects regression | Repeated observations on the same units | Confounders are fixed over time |
Use DiD when a policy hits some units and not others at a known date, and you have data from both sides of that date. If treatment depends on something that changes over time and also drives the outcome, DiD fails; that kind of endogeneity is what instrumental variables are for. On why simple comparisons mislead, see omitted variable bias.
On 1 April 1992 New Jersey raised its minimum wage from $4.25 to $5.05 an hour, while neighbouring eastern Pennsylvania stayed at $4.25. Card and Krueger surveyed 410 fast-food restaurants in both states before and after the rise. Their DiD estimate found no fall in employment in New Jersey relative to Pennsylvania; if anything, employment rose slightly.[2] The result challenged the textbook prediction and started a long debate, including a re-analysis by Neumark and Wascher and a reply by Card and Krueger (both 2000).[9] David Card shared the 2021 Nobel Memorial Prize in Economic Sciences, in part for this work on natural experiments.
The free Econometrics Step 16: Difference-in-Differences and RD walks through the same ideas with more practice.
Practice questions
EasyQ1. A city introduces free school breakfasts. Average attendance in its schools rises from 91.0% to 94.5%. In a similar neighbouring city without the scheme it rises from 92.0% to 93.0%. Compute the DiD estimate. Show worked answer
DiD \( = 3.5-1.0 = 2.5 \) percentage points. Under parallel trends, the breakfasts raised attendance by about 2.5 points.
EasyQ2. In the DiD regression with coefficients \( \beta_0 \) (intercept), \( \beta_1 \) (treated), \( \beta_2 \) (post) and \( \beta_3 \) (treated × post), write the average outcome of the treated group after the policy, and say which coefficient is the effect. Show worked answer
The effect is \( \beta_3 \): the treated group’s change \( (\beta_2 + \beta_3) \) minus the control group’s change \( (\beta_2) \).
MediumQ3. Using the minimum-wage results (\( \hat{\beta}_3 = 2.751 \), clustered s.e. 0.493), construct a 95% confidence interval and test \( H_0\!: \beta_3 = 0 \) at the 1% level. Show worked answer
Test: \( z = 2.751/0.493 = 5.58 \). The 1% two-sided critical value is 2.576. Since 5.58 > 2.576, reject \( H_0 \): the rise in employment relative to the control state is significant at 1%.
MediumQ4. A researcher estimates a DiD with 400 restaurants observed twice and reports an unclustered standard error of 0.977 for the interaction. Explain why this is the wrong standard error and why, in this case, clustering makes it smaller. Show worked answer
The DiD compares changes within restaurants, so the persistent part cancels out of the estimate. The usual formula still counts it as noise in every observation, overstating the variance. The clustered s.e. (0.493) accounts for this correctly.
ExamQ5. A region bans plastic bags in 2023. Average weekly bag-related litter (kg per km of beach) is 12.0 in 2022 and 7.0 in 2024 in the region, and 10.0 and 9.0 in a comparison region. (a) Compute the DiD estimate. [2] (b) State the assumption needed to interpret it as the effect of the ban. [2] (c) The comparison region ran a beach-cleaning campaign in 2024. Explain the direction of the resulting bias. [2] (d) Suggest one check you would carry out with more years of data. [2] Show worked answer
(b) Parallel trends [1]: without the ban, litter in the region would have changed by the same amount as in the comparison region [1].
(c) The campaign lowered litter in the comparison region, so its change (−1.0) overstates the fall that would have happened anyway [1]. Subtracting too large a fall makes the DiD less negative, so the ban’s effect is understated [1].
(d) Plot both regions’ litter for several years before 2023, or run an event study, and check that the pre-ban trends were parallel (leads close to zero) [2].
Frequently asked questions
What is difference-in-differences in simple terms?
It compares how much the outcome changed for the group that experienced a policy with how much it changed for a similar group that did not. The control group’s change stands in for what would have happened anyway.
What is the parallel trends assumption?
It says that, without the treatment, the treated and control groups would have followed the same trend in the outcome. Their levels can differ; their changes must not. It is the one assumption DiD cannot do without.
How do you test parallel trends?
You cannot test it directly, because it concerns an outcome nobody observes. You can examine pre-treatment trends: plot both groups over several periods before the policy, run an event study and check that the lead coefficients are near zero, and run placebo tests on fake policy dates or unaffected outcomes.
How do you interpret the interaction term in a DiD regression?
The coefficient on treated × post is the DiD estimate: the extra change in the treated group relative to the control group. Here, 2.751 means treated restaurants gained about 2.75 more FTE workers than the control group’s trend predicts.
Is difference-in-differences the same as fixed effects?
With panel data, a DiD is a two-way fixed effects regression: unit effects, time effects and a treatment dummy. With two periods, store fixed effects and first differences give the same 2.751. The two ideas diverge with staggered adoption, where the simple two-way fixed effects estimator can be biased.
Should standard errors be clustered in DiD?
Yes. Cluster by the unit observed repeatedly, or by the level at which treatment was assigned if that is coarser (for example, by state when policies vary by state). Unclustered standard errors are usually too small when there are many periods.
Can I use DiD with only two time periods?
Yes, the 2 × 2 case is the basic design. Its weakness is that you cannot look at pre-trends, so parallel trends rests entirely on argument. If you can get earlier data, use it.
Studying more than one subject? The Complete Book Bundle has every Economics, Statistics, Mathematics and Econometrics book on the site in one download.
References
- Wooldridge, J. M. (2020). Introductory Econometrics: A Modern Approach, 7th edn, Chapter 13 “Pooling Cross Sections across Time: Simple Panel Data Methods”. Boston: Cengage Learning.
- Card, D. and Krueger, A. B. (1994). Minimum Wages and Employment: A Case Study of the Fast-Food Industry in New Jersey and Pennsylvania. American Economic Review, 84(4), 772–793.
- Angrist, J. D. and Pischke, J.-S. (2009). Mostly Harmless Econometrics: An Empiricist’s Companion, Chapter 5 “Parallel Worlds: Fixed Effects, Differences-in-Differences, and Panel Data”. Princeton: Princeton University Press.
- Bertrand, M., Duflo, E. and Mullainathan, S. (2004). How Much Should We Trust Differences-in-Differences Estimates? Quarterly Journal of Economics, 119(1), 249–275.
- Roth, J. (2022). Pretest with Caution: Event-Study Estimates after Testing for Parallel Trends. American Economic Review: Insights, 4(3), 305–322.
- Ashenfelter, O. (1978). Estimating the Effect of Training Programs on Earnings. Review of Economics and Statistics, 60(1), 47–57.
- Goodman-Bacon, A. (2021). Difference-in-Differences with Variation in Treatment Timing. Journal of Econometrics, 225(2), 254–277.
- Callaway, B. and Sant’Anna, P. H. C. (2021). Difference-in-Differences with Multiple Time Periods. Journal of Econometrics, 225(2), 200–230.
- Neumark, D. and Wascher, W. (2000). Minimum Wages and Employment: A Case Study of the Fast-Food Industry in New Jersey and Pennsylvania: Comment. American Economic Review, 90(5), 1362–1396; and Card, D. and Krueger, A. B. (2000). Reply. American Economic Review, 90(5), 1397–1420.
- The EconTutorials team (2026). Econometrics Made Simple, Chapter 16 “Policy Evaluation”, dataset
minwage_did.csv. econtutorials.com.

