A fintech wallet app wants to know whether a new cashback loyalty tier increases how often people pay with UPI. Running a clean randomized experiment would mean assigning individual users to "cashback" and "no cashback" groups at random. But the product team cannot do that here: the cashback tier depends on merchant partnerships that are negotiated city by city, and the marketing team insists on a single full-city launch, in Bengaluru, starting in month 7 of the year, so that merchant onboarding and city-wide advertising can be coordinated. By month 12, average monthly transactions per active user in Bengaluru have risen from about 21 to about 27. Did the cashback program cause that rise, or did UPI usage across India simply keep climbing that year regardless, the way it has climbed every year since 2016? A before-and-after comparison inside Bengaluru alone cannot tell the two apart, because it has no way to represent what Bengaluru's transaction volume would have looked like in months 7 to 12 if the program had never launched. That unobserved quantity, the counterfactual, is the entire problem of causal inference, and this chapter builds the machinery economists and data scientists actually reach for when a controlled experiment is not on the table: the potential-outcomes framework, the difference-in-differences estimator, and the synthetic control method. This is a different toolkit from the graph-based apparatus of causal DAGs and instrumental variables you may already have met in "Causal Inference in Machine Learning" or in the Grade 10 introduction to causal inference; those tools ask "which arrows in this graph create bias, and how do I block them." The tools here ask a different question: given repeated observations on a treated group and an untreated group over time, how much of the treated group's change can be attributed to something other than the shared passage of time?
The potential-outcomes framework, precisely
Formalize the problem before reaching for an estimator. For every unit i (a user, a city, a state) there exist two potential outcomes: Yi(1), the outcome unit i would show if treated, and Yi(0), the outcome it would show if untreated. Let Di be 1 if unit i actually receives treatment and 0 otherwise. What we observe is only Yi = Di·Yi(1) + (1 − Di)·Yi(0): the realized outcome under whichever state actually happened. This framework, formalized by Donald Rubin in "Estimating Causal Effects of Treatments in Randomized and Nonrandomized Studies" (Journal of Educational Psychology, 1974), gives causal inference its sharpest possible statement, usually called the fundamental problem of causal inference: for any single unit, at most one of Yi(1) and Yi(0) is ever observed. Bengaluru in month 12 either got the cashback program or it didn't; there is no second Bengaluru running in parallel without it. The individual treatment effect τi = Yi(1) − Yi(0) is therefore not a quantity we can compute from data, ever, for any specific unit. What we can estimate, under the right assumptions, are population averages: the average treatment effect ATE = E[Yi(1) − Yi(0)], and the average treatment effect on the treated, ATT = E[Yi(1) − Yi(0) | Di = 1]. Under random assignment, treated and control units are exchangeable in expectation, so E[Y(0) | D=1] = E[Y(0) | D=0], and the naive difference of sample means is an unbiased estimator of the ATE. In observational settings like the Bengaluru rollout, that exchangeability fails: Bengaluru was not picked at random, it was picked because it is a metro with strong UPI merchant density, and cities that get picked for pilots typically differ systematically, in level and in trajectory, from cities that don't. The gap between the two is exactly the selection bias that a naive before/after or treated/control comparison inherits. Difference-in-differences is a specific strategy for neutralizing one large piece of that selection bias using panel structure, without needing randomization.
Difference-in-differences: using the control group's own trend as the counterfactual
Suppose you observe an outcome Yit for unit i at time t, for two groups: a treated group (Bengaluru) and a control group (a comparison city that never got the cashback tier), across a pre-period and a post-period. Define Treatedi = 1 for the treated group and Postt = 1 for periods at or after the intervention. The difference-in-differences (DiD) estimator is
τDiD = [E(Y | Treated=1, Post=1) − E(Y | Treated=1, Post=0)] − [E(Y | Treated=0, Post=1) − E(Y | Treated=0, Post=0)]
In words: take the treated group's own before/after change, then subtract the control group's before/after change over the same calendar window. The logic is that whatever the control city experienced between the pre- and post-periods, a national UPI adoption wave, a festive-season transaction spike, an RBI policy change, the treated city would plausibly have experienced too, absent its own program. Subtracting the control's change purges that shared drift, leaving (in principle) just the effect of the thing that differed between the two cities: the cashback program. This subtraction is only valid under one identifying assumption, the parallel trends assumption: in the absence of treatment, the treated group's outcome would have moved in parallel with the control group's outcome, i.e. E[Yit(0) − Yi,t−1(0) | Treated=1] = E[Yit(0) − Yi,t−1(0) | Treated=0]. Note precisely what this assumption does and does not require: it says nothing at all about the two groups having the same level of the outcome before treatment. Bengaluru can start at a higher transaction volume than the control city; DiD is indifferent to that, because a constant level gap cancels out in the "differencing" step. What it requires is that the two groups' trajectories, their slopes over time, would have matched had neither been treated. This is precisely the design David Card and Alan Krueger used in their well-known 1994 study of a New Jersey minimum-wage increase, comparing fast-food employment changes in New Jersey against neighboring Pennsylvania, which kept its minimum wage fixed, as the control (Card & Krueger, "Minimum Wages and Employment," American Economic Review, 84(4), 1994).
Worked example: does the cashback tier move transactions?
Build the Bengaluru scenario with numbers you can check by hand. Let t index months 1 through 12, with the cashback program launching in Bengaluru at the start of month 7. Suppose the control city's average monthly transactions per active user follow control(t) = 18 + 0.2(t−1), a slow organic uptrend with no program. Suppose Bengaluru, absent any program, would have followed the same 0.2-per-month uptrend but from a higher base: base(t) = 20 + 0.2(t−1). From month 7 onward, the actual program adds a flat +5 to Bengaluru's trajectory on top of that base, so Bengaluru's observed value is base(t) for t ≤ 6 and base(t) + 5 for t ≥ 7. Averaging each series over the pre-period (months 1–6) and post-period (months 7–12) gives the four cell means below.
| Group | Pre-period mean (months 1–6) | Post-period mean (months 7–12) | Change |
|---|---|---|---|
| Treated (Bengaluru) | 20.5 | 26.7 | +6.2 |
| Control (comparison city) | 18.5 | 19.7 | +1.2 |
| Difference-in-differences | 6.2 − 1.2 = 5.0 | ||
Bengaluru's raw before/after change is +6.2, but 1.2 of that is attributable to the same organic drift the control city shows on its own, since the control city's own trajectory rose by 1.2 over the identical window with no program at all. Subtracting it leaves 5.0, matching the flat +5 we built into the simulation exactly. This is not a coincidence of a favorable dataset; it demonstrates that the estimator recovers the true parameter when its identifying assumption (here, parallel pre-existing trends by construction) actually holds. The same arithmetic can be recovered from a single regression instead of a four-cell table, which is how DiD is estimated in practice once there are covariates or many time periods to control for. Encode Treatedi and Postt as 0/1 dummies and estimate
import pandas as pd
import statsmodels.formula.api as smf
months = list(range(1, 13))
control = [18 + 0.2 * (t - 1) for t in months]
treated = [20 + 0.2 * (t - 1) + (5 if t >= 7 else 0) for t in months]
rows = []
for t in months:
rows.append({"y": treated[t - 1], "treated": 1, "post": 1 if t >= 7 else 0})
rows.append({"y": control[t - 1], "treated": 0, "post": 1 if t >= 7 else 0})
df = pd.DataFrame(rows)
model = smf.ols("y ~ treated * post", data=df).fit()
print(model.params.round(3))
Trace this line by line. months is 1 through 12. control and treated build the exact two series described above, list comprehensions with no names. The loop appends 24 rows total, one per (city, month) pair, each carrying the outcome y and the two dummy columns. smf.ols("y ~ treated * post", ...) expands to the four-parameter model y = β0 + β1·treated + β2·post + β3·(treated·post) + ε. Because treated and post together define exactly four mutually exclusive cells and the model has exactly four free parameters, one per cell, this is a saturated model: OLS reproduces the four cell means exactly, regardless of how much y varies month to month within a cell, which is the standard equivalence between a fully-interacted dummy regression and a direct table of group means. So the printed output is fully determined by the table above and can be stated with certainty:
Intercept 18.500
treated 2.000
post 1.200
treated:post 5.000
dtype: float64
The intercept is the control group's pre-period mean (18.5). The treated coefficient is the pre-period gap between the two cities (20.5 − 18.5 = 2.0), a pure level difference that DiD is explicitly designed to absorb and ignore. The post coefficient is the control group's own before/after change (19.7 − 18.5 = 1.2), the shared drift. The treated:post interaction coefficient, 5.0, is the DiD estimator itself, and it is the only one of the four numbers that answers the causal question: how much of Bengaluru's change is attributable to something Bengaluru alone experienced starting in month 7.
Common misconception: "parallel trends" does not mean "parallel levels"
Students who first meet DiD often conclude that the method demands the treated and control groups look statistically similar before treatment, similar average outcome, similar variance, and treat any pre-existing gap between the two as disqualifying. That is a genuine misreading of the identifying assumption. In the worked example above, Bengaluru's pre-period average (20.5) is noticeably higher than the control city's (18.5), a persistent 2.0-unit gap, and the method works perfectly regardless, because that gap is a constant that cancels the moment you difference twice. What the method actually requires is that the two series' slopes over the pre-period would have stayed matched into the counterfactual post-period; a large, stable level gap is completely compatible with that. The practical corollary is what applied researchers actually check before trusting a DiD estimate: not "do the groups look alike," but "do the two lines run parallel before the intervention." This is usually done with an event-study plot, estimating a separate treated×month coefficient for every pre-period month relative to a baseline month and checking that they hover near zero with no drift, rather than jumping straight to the two-period average used above. A visible pre-trend, the treated group already diverging from the control before month 7, is the actual red flag; a level gap is not.
When there is no good comparison group: synthetic control
DiD needs a control group whose trend you trust as the counterfactual. That is easy to arrange with two comparable cities; it gets much harder when the treated unit is genuinely unusual, a single state rolling out a unique policy, a single large city with an atypical economy, and no single other unit is a convincing stand-in for its counterfactual trajectory. Abadie, Diamond and Hainmueller proposed a solution in "Synthetic Control Methods for Comparative Case Studies: Estimating the Effect of California's Tobacco Control Program" (Journal of the American Statistical Association, 105(490), 2010), building on Abadie and Gardeazabal's earlier study of the economic cost of terrorism in the Basque Country (2003). Instead of picking one control unit, assemble a donor pool of several untreated units, other Indian metro cities in the Bengaluru example, Chennai, Pune, Hyderabad, Ahmedabad, and construct a synthetic Bengaluru as a weighted average of them: synthetic(t) = Σj wj·cityj(t), with weights constrained to wj ≥ 0 and Σj wj = 1. The weights are chosen by solving a constrained least-squares problem: minimize the squared gap between Bengaluru's actual pre-period trajectory (and, in the fuller version of the method, other predictor variables like average ticket size or merchant density) and the weighted combination's pre-period trajectory. If the optimizer lands on, say, wChennai=0.55, wPune=0.30, wHyderabad=0.15, wAhmedabad=0, that weighted blend is, by construction, the closest achievable pre-treatment twin for Bengaluru out of the donor pool. Extending that same blend into the post-period and comparing it against Bengaluru's actual post-period values gives the estimated program effect, exactly as the treated-vs-counterfactual gap did in the DiD chart, except the counterfactual is now a bespoke, data-optimized blend rather than one single comparison city's raw trajectory. Abadie, Diamond and Hainmueller applied this to California's 1988 tobacco-control program (Proposition 99): a synthetic California, built from a weighted blend of other U.S. states matched on pre-1988 cigarette sales and covariates like income and beer consumption, tracked California's actual cigarette consumption closely before 1988 and then diverged sharply afterward, with the gap read as the program's effect on per-capita cigarette sales. Because there is only one treated unit, conventional standard errors do not apply cleanly; the paper's answer is a placebo, or permutation, inference procedure: rerun the identical synthetic-control procedure treating each untreated donor unit as if it, not California, were the treated unit, and check whether California's actual post/pre fit-error ratio is an outlier against that whole distribution of placebo ratios. A large, unusual gap for the real treated unit relative to the placebo runs is evidence the effect is not simply noise.
Both DiD and synthetic control lean on an assumption worth naming even though neither method states it out loud: the stable unit treatment value assumption (SUTVA), that one unit's treatment status does not change another unit's potential outcomes, and that "treatment" means the same thing for every treated unit. It is not automatically true here. If Bengaluru users refer friends in Chennai into the app and those referrals redeem the same cashback offer, or merchants operate storefronts in both cities, Chennai's own trajectory is contaminated by Bengaluru's treatment, which is exactly the kind of interference that breaks the "control tells us the counterfactual" logic both methods depend on. Recognizing when a donor or control unit might be indirectly affected by the treatment is as important as picking donor weights correctly.
Where DiD and synthetic control both eventually run out of room is high-dimensional confounding: many time-varying covariates, no obvious small donor pool, effects that plausibly differ by user segment. That is the regime where more recent estimators combining machine learning with the potential-outcomes framework, such as double/debiased machine learning (Chernozhukov, Chetverikov, Demirer, Duflo, Hansen, Newey and Robins, "Double/Debiased Machine Learning for Treatment and Structural Parameters," The Econometrics Journal, 21(1), 2018), take over; that is a topic for a follow-on treatment, not this chapter, but it is worth knowing the panel-based tools here are a stepping stone to it, not a dead end.
Active recall
Attempt each question before reading its answer.
1. In potential-outcomes notation, define the ATT, and explain precisely why it cannot be computed directly from data for any single treated unit.
Answer: ATT = E[Yi(1) − Yi(0) | Di = 1], the average gap between the treated and untreated potential outcomes, restricted to units that were actually treated. For any specific treated unit i, only Yi(1) is ever observed; Yi(0), what that same unit's outcome would have been without treatment, never happens and is never recorded, which is the fundamental problem of causal inference. ATT is therefore not computed by looking up individual values, it is estimated by substituting an identifying assumption (such as parallel trends) that lets some other observed quantity, here the control group's own change over time, stand in for the missing E[Y(0) | D=1].
2. Suppose the control city, independent of anything Bengaluru did, also ran its own unrelated promotion starting in month 9, adding a flat +2 to its transactions for months 9 through 12 only (months 7 and 8 unaffected). Recompute the DiD estimate using the same pre-period (months 1–6) and post-period (months 7–12) definitions, and explain the direction of the change.
Answer: Only the control series changes. Its post-period values become 19.2, 19.4, 21.6, 21.8, 22.0, 22.2 for months 7–12 (months 9–12 each +2). The new post-period control mean is (19.2+19.4+21.6+21.8+22.0+22.2)/6 = 126.2/6 = 21.0333. The control's before/after change is now 21.0333 − 18.5 = 2.5333, versus 1.2 before. Bengaluru's own before/after change is unaffected at 6.2. The new DiD estimate is 6.2 − 2.5333 = 3.6667, down from 5.0. There is a shortcut that checks this: only 4 of the 6 post-period months carry the extra +2, so the average boost added to the control's post-period mean is 2 × (4/6) = 1.3333, and 5.0 − 1.3333 = 3.6667, matching exactly. The DiD estimate falls because the method attributes part of Bengaluru's true +5 effect to the control's own unrelated promotion; this is precisely a parallel-trends violation, since the assumption requires the control's trajectory to represent what Bengaluru would have done with no program of its own, and that stops being true once the control receives an independent intervention mid-window.
3. A colleague argues that DiD "controls for all confounders" because it differences out both groups. Name one class of confounder DiD actually removes and one class it cannot, using the Bengaluru example for each.
Answer: DiD removes (a) time-invariant level differences between the treated and control units, such as Bengaluru having a wealthier, more tech-adopting user base on average, which shows up as the constant "treated" coefficient and cancels in the double subtraction, and (b) time trends common to both groups, such as a nationwide UPI growth wave, which shows up as the "post" coefficient and also cancels. It cannot remove a confounder that is both time-varying and differentially affects only the treated unit around the treatment date, for example Bengaluru airport rolling out a new contactless payment system in month 7 coinciding with the cashback launch, or the scenario in question 2, where the control itself receives a second, independent treatment during the post-period.
4. You have monthly data since month 1 for five other Indian metro cities besides Bengaluru. Describe the optimization problem for building a synthetic Bengaluru, what the resulting weight vector means, and why it can beat a simple five-city average as a control.
Answer: Choose non-negative weights wj for each donor city, constrained to sum to 1, that minimize the squared difference between Bengaluru's actual pre-treatment trajectory (months 1–6, and any other pre-treatment predictors used) and the weighted combination Σwj·cityj(t) over that same window. The resulting weights say how much of each donor city's trajectory is needed to best reconstruct Bengaluru's own pre-treatment path, for example mostly Chennai with smaller contributions from Pune and Hyderabad. This beats a simple unweighted average because an equal-weight average treats a poorly-matching city (say, one on a very different growth trajectory) the same as a closely-matching one, diluting the counterfactual's accuracy; the optimized weights instead down-weight or exclude cities that do not track Bengaluru's actual pre-period behavior, producing a tighter pre-treatment fit and a more credible post-treatment gap.
5. If you estimated a separate treated×month coefficient for every one of the 12 months (an event-study specification) instead of collapsing to two periods, what pattern in the months-1-to-6 coefficients would increase your confidence in the design, and what pattern would undermine it?
Answer: Confidence increases if the pre-period coefficients (relative to a chosen baseline month) sit close to zero with no visible trend, evidence the two cities were moving in parallel before month 7, consistent with the parallel-trends assumption. Confidence is undermined if the pre-period coefficients show a rising or falling pattern before month 7, meaning Bengaluru was already diverging from the control before the program launched; that could reflect anticipation effects (merchants or users adjusting behavior ahead of an announced launch) or reflect that Bengaluru was picked for the pilot precisely because it was already on a different trajectory, either of which invalidates using the control's post-period path as Bengaluru's counterfactual.
6. Both DiD and synthetic control assume SUTVA. State what SUTVA requires here and describe one realistic way the Bengaluru cashback rollout could violate it.
Answer: SUTVA requires that one unit's treatment assignment does not alter another unit's potential outcomes (no interference between units) and that "treatment" is a single well-defined intervention rather than varying in form across treated units. It could be violated if Bengaluru users refer friends or family in the control city (or in donor cities used for synthetic control) into redeeming the same cashback offer, so that the "untreated" city's transaction volume is itself nudged upward by Bengaluru's treatment; in that case the control or donor cities no longer represent an untouched counterfactual, and both DiD and synthetic control would understate the true effect, since part of the program's impact leaks into the very group being used to estimate what "no program" would have looked like.
Think About It
Think about this: How would you explain causal inference: beyond correlation to a friend who has never seen a computer? What real-world analogy would you use? Imagine you had to build a system using these concepts — what would be your first step? Try this: before moving on, write down three things you learned and one question you still have.
Key Takeaways — Summary and Recap
Let us recap what we covered: the core ideas behind causal inference: beyond correlation, how they connect to real-world applications, and why they matter for your journey in computer science. Remember these key points as you move forward. For competitive exam preparation (CBSE, JEE, BITSAT), focus on understanding the WHY behind each concept, not just the WHAT.