Imported from Jill0099/causal-inference-mixtape (
SKILL.md). Install upstream withnpx skills add Jill0099/causal-inference-mixtape. Copyright stays with the author.
name: causal-inference-mixtape description: This skill should be used when the user asks to "implement a DiD regression", "run a staggered difference-in-differences", "set up an event study", "implement IV / 2SLS", "run a regression discontinuity design", "build synthetic control", "do propensity score matching", "test parallel trends", "run Honest DiD", "wild cluster bootstrap", "Callaway-Sant'Anna", "Sun-Abraham", "Bacon decomposition", "double machine learning", "debiased machine learning", "DML / DoubleML", "cross-fitting", "causal forest", "heterogeneous treatment effects", "ATE with ML controls", "which causal design fits my data", or needs causal-inference code, diagnostics, or identification writing in Python (StatsPAI), R, or Stata. Based on Scott Cunningham's Causal Inference: The Mixtape, with runnable validated templates, ML-based causal inference patterns, and Journal of Finance applications. version: 3.1.0
Causal Inference: The Mixtape — Code Skill (v3.1)
Practitioner-oriented causal inference: route from the assignment mechanism to a design, implement it in Python / R / Stata, run the diagnostics that make it publishable, and write the identification section without over-claiming.
Based on Scott Cunningham's Causal Inference: The Mixtape, extended with 25 Journal of Finance (2021-2024) applications and ML-based causal inference patterns for DML, causal forests, and heterogeneous treatment effects.
The core Python validation suite runs against the Mixtape's own public
data. python scripts/validate_all.py runs all 13 bundled scripts and asserts
cross-backend agreement — currently 13/13 passing. The DML material in §15 is
reference code and is not part of that 13-script validation suite.
Start here: route the design before writing code
Users describe a setting, not a method. Ask how treatment was assigned, then route:
How was treatment assigned?
├─ Randomised -> diff in means + RI (09)
├─ Threshold on a running variable -> RDD / fuzzy / diff-in-disc (05)
├─ Policy date, one date for all -> 2x2 DiD -> event study (02, 03)
├─ Policy date, dates VARY -> staggered: Bacon -> CS/SA/BJS (04)
├─ One treated unit, many controls -> synthetic control (07)
├─ Self-selected + an instrument -> IV / 2SLS, identifies a LATE (06)
├─ Self-selected + rich observables -> matching / IPW / DML (08)
└─ None of the above -> say so; use associational language
Full tree, estimator choice within each design, and a StatsPAI second opinion
(sp.detect_design, sp.recommend, sp.preflight):
references/design-router.md.
When the design is unsettled, also load references/method-selection.md.
It maps research setting → identifying assumption → method → falsification
check, with Chinese-language explanations and links to worked Stata tutorials.
Python backends: choose by estimator and replication target
import statspai as sp # pip install statspai
StatsPAI is one supported
Python backend for this skill. It covers a broad Stata/R causal-inference surface
natively — regress, ivregress, reghdfe, csdid, rdrobust, synth,
psmatch2, outreg2 and their R equivalents — plus Bacon decomposition,
Callaway-Sant'Anna, Sun-Abraham, Honest DiD, wild cluster bootstrap, DAG
identification, and Conley SEs.
Do not assume that Python lacks a method; check current implementations first.
Choose StatsPAI, pyfixest, linearmodels, R, or Stata according to estimator
maturity, independent validation, and the replication target. See
references/statspai-guide.md for the StatsPAI API map and cross-backend
checks.
Disclosure: the v3 StatsPAI integration was contributed by StatsPAI's maintainer. Keep independent cross-checks for headline estimates and do not treat package choice as an identification argument.
Complementary backends: pyfixest for fast HDFE and an independent wild
bootstrap; linearmodels for deep IV/panel diagnostics; statsmodels for plain
OLS/GLM; and R or Stata when the reference implementation or replication target
requires them.
There is also an MCP server (statspai-mcp): prefer it when the user wants
an answer; prefer generating a script when they want a reproducible artefact.
Methods Covered
| Method | Python options | R | Stata | Script | Reference |
|---|---|---|---|---|---|
| Potential outcomes / selection bias | — | — | — | 01 |
mixtape-core.md §1 |
| OLS / regression | sp.regress |
estimatr | reg, reghdfe |
— | method-patterns.md §1 |
| DiD (2×2) | sp.feols |
fixest | reghdfe | 02 |
§2 |
| Event study | sp.event_study |
fixest i() |
reghdfe | 03 |
§3 |
| Staggered DiD | sp.callaway_santanna, sp.sun_abraham, sp.did_imputation |
did, fixest | csdid | 04 |
§4 |
| Bacon decomposition | sp.bacon_decomposition |
bacondecomp | bacondecomp | 04 |
§4 |
| Regression discontinuity | sp.rdrobust, sp.rddensity |
rdrobust | rdrobust | 05 |
§5 |
| Instrumental variables | sp.ivreg |
AER, fixest | ivregress | 06 |
§6 |
| Synthetic control / SDiD | sp.synth, sp.sdid |
Synth, synthdid | synth, sdid | 07 |
§7 |
| Matching / PSM / IPW | sp.match, sp.ipw, sp.psmatch2 |
MatchIt | teffects, cem | 08 |
§8 |
| Double / Debiased ML | DoubleML, EconML | DoubleML, grf | ddml, pdslasso | — | §15; dml-causal-ml.md |
| DAGs / collider bias | sp.dag, dowhy |
dagitty | — | sim_collider_bias |
§9 |
| Randomisation inference | sp.ri_test |
ri2 | ritest | 09 |
§10 |
| Clustered inference / wild bootstrap | sp.wild_cluster_bootstrap |
fwildclusterboot | boottest | 10 |
inference-and-standard-errors.md |
| Honest DiD / pre-trend power | sp.honest_did, sp.pretrends_power |
HonestDiD | honestdid | 11 |
ibid. §5 |
| Diff-in-discontinuities | sp.rdrobust + sp.feols |
rdrobust + fixest | rdrobust | — | §11 |
| Shift-share / weather IV | sp.feols IV syntax |
fixest | ivreghdfe | — | §12 |
| Saturated interacted FE | sp.feols("y ~ x | a^b + c") |
fixest | reghdfe | — | §13 |
| Financial event study | manual CAR | eventstudies | eventstudy2 | — | §14 |
Core Workflow
- Route the design from the assignment mechanism (
design-router.md), usingmethod-selection.mdwhen the setting or identifying assumption is still unclear - Load the template from
method-patterns.md; use the corresponding runnable version inscripts/when one is listed in the methods table - Adapt variable names, FE structure and clustering — cluster at the level of treatment assignment (Abadie-Athey-Imbens-Wooldridge 2023)
- Diagnose with the design's required checks (
reporting-checklist.md§3) - Report N, cluster count, treated share, baseline mean, and economic
magnitude — never a t-statistic alone (
reporting-checklist.md§1) - Write the identification paragraph with a verb the design supports
(
identification-writing-patterns.md§3)
Common Pitfalls
The numbered script references below point to live demonstrations. General design and DML cautions without a script reference are documentation guidance, not claims of executed validation.
- TWFE with staggered treatment. In simulation with effects growing at 1.0
per period, the true ATT is 6.832 and TWFE reports 3.173 — a 54% understatement.
Run
sp.bacon_decomposition, then report Callaway-Sant'Anna or Sun-Abraham as the headline. →sim_twfe_staggered_bias.py - Event study with the reference period not actually dropped.
range(-4, 0)contains −1. Without omitting it the model is collinear and there is no normalisation; and endpoints must be binned, not zeroed. →03 - Main effects collinear with fixed effects.
C(treated)*C(post)alongside entity and year FE: statsmodels uses a pseudo-inverse and silently splits the coefficient instead of dropping a term. Include the interaction only. →02 - "The pre-trends look flat" is not a test. On
castle.dtathat test has power 0.50 individually and 0.14 jointly. Report Honest DiD and the breakdown M instead. →11 - Too few effective clusters. CRVE is justified as the number of clusters
grows, but there is no universal safe cutoff: imbalance, leverage, and the
number of treated clusters matter. Add a small-sample correction when the
approximation is doubtful. Use randomisation inference only when the
assignment mechanism justifies the permutations. →
10 - Clustering finer than assignment. State-year instead of state shrinks the
SE by 57% on
castle.dta. Cluster where treatment was assigned. →10 - Manual two-step 2SLS. Reproduces the point estimate exactly and reports
the wrong standard error; the direction of the error is data-dependent. →
06 - The forbidden regression. A logit first stage plugged in as a regressor
is inconsistent — on Card it flips sign versus linear 2SLS. Use it as an
instrument instead. →
06 - RDD without a manipulation test. Run
sp.rddensitybefore estimating. And put only predetermined variables in the balance table — the treatment indicator is supposed to jump. →05 - Synthetic control t-ratios. With one treated unit there is no sampling
distribution. On
texas.dtathe t-ratio is 7.74 while the permutation p-value is 0.18. Report the rank. →07 - IPW without checking overlap. Only 30% of CPS controls lie inside the
treated propensity support. Untrimmed weights put 7% of total weight on one
observation. And verify whether your library drops or clips — on
NSW/CPS that is a $9,400 difference. →
08 - Matching without bias correction or matching-appropriate SEs. With >1
continuous covariate the Abadie-Imbens bias does not vanish asymptotically,
and the post-match OLS standard error is wrong. →
08 - Adding controls is not safer. Colliders and mediators bias you by being
included. A collider control produces a higher R², a lower residual
variance, and a t of −78 on a coefficient whose truth is zero. →
sim_collider_bias.py - Fixed effects absorbing the treatment.
county × yearFE eats any state-level policy. Check what the FE structure consumed. - Permutation / bootstrap p-values of exactly 0. The
+1correction is not optional; the smallest attainable value is1/(1+B). →09 - Non-causal framing. "Factor X captures the cross-section" is a spanning
claim. Do not write "causes" without exogenous variation.
→
identification-writing-patterns.md§3 - Cross-country panels with rich FE. Fixed effects reduce confounds; they do not create exogenous variation.
- Multiple testing. Apply Romano-Wolf or a FDR correction before trusting
any single α from a scan. →
inference-and-standard-errors.md§7 - DML without cross-fitting. In-sample nuisance predictions reintroduce
regularisation bias. Use out-of-fold prediction, vary the nuisance learners,
and remember that DML addresses estimation under high-dimensional controls,
not identification: an ATE interpretation still requires unconfoundedness.
→
dml-causal-ml.md
Reference Files
| File | What it is for |
|---|---|
references/design-router.md |
Assignment mechanism → design → estimator → required diagnostics |
references/method-selection.md |
Chinese design-selection guide: setting → assumption → method → falsification check |
references/statspai-guide.md |
StatsPAI API/integration guide, verified numbers, and 11 gotchas |
references/method-patterns.md |
Code templates for all methods, Python / R / Stata, including DML in §15 |
references/dml-causal-ml.md |
DML model classes, cross-fitting, causal forests, and the DeDL frontier |
references/lianxh-stata-index.md |
Chinese-language Stata tutorial index mapped to method sections |
references/mixtape-core.md |
Potential outcomes, DAGs, matching theory, LATE, panel FE, staggered DiD |
references/inference-and-standard-errors.md |
Clustering, small-cluster bootstrap, Honest DiD, RI, multiple testing |
references/reporting-checklist.md |
What to print alongside every estimate, by design |
references/r-stata-comparison.md |
Cross-language coverage matrix and package roles |
references/finance-applications.md |
25 JF papers indexed by method: Y / D / unit / FE / clustering / data |
references/jf-case-studies.md |
Five end-to-end finance worked examples |
references/identification-writing-patterns.md |
Identification paragraphs, verb guide, robustness checklists |
Runnable Scripts
scripts/ — 13 validated templates plus _common.py (Mixtape data loader) and
validate_all.py. Run python scripts/validate_all.py --list to see them all,
or --quick to skip the slow one.
Prompt Files
prompts/01-implement-method.md · 02-robustness-checks.md ·
03-finance-application.md · 04-statspai-workflow.md