Causal Inference

Evaluating the Impact of Infrastructure: A Beginner's Guide to Difference-in-Differences with the Jamuna Bridge

In June 1998 a 4.8-kilometre bridge over the Jamuna river connected 26 million isolated Bangladeshis to Dhaka and cut freight costs in half. This tutorial rebuilds the difference-in-differences evaluation of that bridge from the ground up in Python, using the Padma hinterland — a symmetric region left isolated by a river whose own bridge was not started until 2015 — as the comparison group. It teaches the 2x2 logic, parallel trends, two-way fixed effects, event studies and honest sensitivity analysis on satellite nighttime lights, then runs the same machinery over census employment shares, rice yields and a public-goods placebo. The two doubly robust estimators of the original paper are rebuilt by hand in NumPy and pushed through both diff-diff and pyfixest. All 122 published coefficients are audited side by side with the replication, and the defects found inside the shipped Stata package are documented in full.

Bayesian Spatial Synthetic Control in Python: California's Proposition 99 with scspill and mlsynth

A ground-up introduction to synthetic control in Python, built on the California Proposition 99 case study and climbing three stages: the classical simplex of Abadie, Diamond and Hainmueller; a Bayesian horseshoe prior that lets the data rather than a constraint choose the donors; and the Bayesian spatial model of Sakaguchi and Tagawa, which drops SUTVA on the donor pool and asks who else was treated. Every equation is derived and mapped to the code that implements it, using the scspill and mlsynth libraries. The answer for California survives every relaxation. The claim that the donor pool was clean does not.

The Synthetic Control Ladder in Python: A Guided Tour of mlsynth on the Brexit Referendum

A careful introduction to mlsynth, the Python library that puts the whole family of single-treated-unit synthetic control estimators behind one configuration interface. We climb the ladder from difference-in-differences to synthetic difference-in-differences with one mlsynth class per stage, showing what every option does and where the defaults will quietly hand you a different estimator. The case study is the 2016 Brexit referendum and what it cost UK GDP.

From DiD to SDID: A Ladder of Synthetic Control Estimators, and What Brexit Cost the UK

Climbing the ladder from difference-in-differences to synthetic difference-in-differences, one stage at a time, with every estimator hand-coded before it is run with its package. The case study is the 2016 Brexit referendum and what it cost UK GDP. Includes cheat sheets in R, Stata and Python.

Do Industrial Parks Work? Evaluating Place-Based Policy in Ethiopia with Difference-in-Differences

Do industrial parks raise local economic activity — and for whom? A beginner's staggered difference-in-differences evaluation of Ethiopian industrial parks in Python, replicating Huang, Wang & Xu (2026) on synthetic calibrated data: TWFE and an event study with pyfixest, the modern Sun-Abraham, Borusyak/Gardner and Callaway-Sant'Anna estimators plus a Goodman-Bacon decomposition with diff-diff, survey-weighted repeated-cross-section DiD on DHS household welfare and women's empowerment, and Conley spatial standard errors.

Bouncing Back Better? Evaluating the Economic Impact of the Aceh Tsunami

Evaluate the long-run economic impact of a localized natural disaster with causal inference in Python. A beginner's replication of Heger & Neumayer (2019) on the 2004 Aceh tsunami, using synthetic calibrated data: dynamic difference-in-differences with pyfixest, an event study with diff-diff, a night-lights dose-response, synthetic control with mlsynth, and Conley spatial standard errors.

The Augmented Synthetic Control Method: A Beginner's Tutorial with the Kansas Tax Cuts

A beginner-friendly, intuition-first tutorial on the Augmented Synthetic Control Method (ASCM) for a single treated unit — estimating the effect of the 2012 Kansas tax cuts on GDP per capita with the augsynth package, from classic SCM to ridge augmentation, with a careful tour of four ways to do inference.

Staggered Synthetic Difference-in-Differences (SDID) in Stata: Gender Quotas and Women in Parliament

Extend synthetic difference-in-differences to staggered adoption, where units adopt treatment at different times, and apply it in Stata to parliamentary gender quotas across 119 countries — deriving the per-cohort estimator, its aggregation into the overall ATT, the modern sdid_event event study, and bootstrap, jackknife, and placebo inference.

Synthetic Difference-in-Differences (SDID) in Stata: Re-evaluating California's Proposition 99

Introduce and derive synthetic difference-in-differences, then apply it to California's Proposition 99 — comparing SDID with the original difference-in-differences and synthetic control (synth2), and how to run placebo inference with a single treated unit.

Double LASSO in Python: Does Abortion Reduce Crime?

Python companion to the R and Stata Double LASSO tutorials — same data, same five estimators, plus a hands-on introduction to the DoubleML library (DoubleMLPLR, DoubleMLIRM, and learner-robustness across LASSO, RandomForest, XGBoost).