Full Empirical Analysis — Classical Stata Workflow
SkillDev toolsOnce added, your AI can carry out complete empirical analyses in Stata, taking a project from data cleaning through to publication-ready regression tables and figures. The skill follows the classical workflow of the traditional Stata ecosystem and guides each step of the analysis.
Available today. Use it from your connected AI after setup.
No other account needed.
Add the skill, then give your AI a dataset and the research question you want to study. It will work through the analysis step by step and deliver the resulting tables and figures.
Then ask your AI: use the Full Empirical Analysis — Classical Stata Workflow skill
What your AI can do with it
- Clean and prepare datasets for analysis
- Run fixed effects and instrumental variables regressions
- Estimate difference-in-differences and event study designs
- Apply regression discontinuity and synthetic control methods
- Match treated and control groups to estimate treatment effects
- Produce publication-ready regression tables and figures
What this skill tells your AI
The instructions your AI receives, as published by brycewang-stanford/auto-empirical-research-skills in skills/00.2-Full-empirical-analysis-skill_Stata/SKILL.md and read by ahel’s review.
This skill is the canonical 8-step pipeline an applied economist runs on every empirical paper, written in the traditional Stata ecosystem — native Stata + the 20+ community commands that have become de-facto standards (reghdfe, ivreg2, csdid, did_imputation, eventstudyinteract, sdid, rdrobust, rddensity, synth, synth_runner, psmatch2, teffects, ebalance, coefplot, esttab, outreg2, boottest, ritest, rwolf, bacondecomp, honestdid, binscatter).
Companion skills: if the user wants the same pipeline in Python, route to 00-StatsPAI_skill (agent-native DSL) or 00.1-Full-empirical-analysis-skill (explicit Python stack). This skill is the Stata counterpart — every step produces a .do file you can hand to a journal's replication office or a co-author who refuses to leave Stata.
Philosophy
- Stata idioms, not Python-translated.
reghdfe, not "statsmodels analogue of reghdfe".esttab, not "Stata's stargazer". - Reproducible .do files. Every code block below is runnable after
use data.dta, clear. No Jupyter, no notebooks — just do-files and log files. - Full pipeline, not just regressions. Stata users historically over-invest in Step 5 (modeling) and under-invest in Steps 1–4 and 6–8. This skill treats them as first-class.
- Rich outputs. Every step yields at least one table (
.tex/.rtf) or figure (.pdf/.png) — never a coefficient printed to the Results window and forgotten. - Progressive disclosure.
SKILL.mdgives the canonical command at each step;references/holds variant-specific depth (dozens of tests, estimator-specific diagnostics, graph recipes).
SkillOpt-style execution gate
Use this long playbook as a seed skill, not as a script to exhaustively apply. SkillOpt discipline: treat each local .do-file change as a candidate patch that must beat a selection check and survive a held-out check before it becomes reusable boilerplate. Before writing or revising a .do file, compress the user's request into a task-local best_skill card:
best_skill: <mode + design + artifact target>
train_signal: <current failure, user goal, or missing evidence>
selection_split: <focal dataset/spec/output used to judge the candidate>
heldout_gate: <checks the patch must pass beyond the focal example>
accepted_patterns: <rules to reuse after validation>
rejected_patterns: <failed shortcuts not to retry without new evidence>
patch_scope: <one estimator/sample/export/robustness change>
reject_if: <conditions that force rollback to the last passing spec>
- Route card: record the mode (
econ,epi, orml-causal), estimand, identification design, focal outcome/treatment, Stata command family, and required artifacts. - Bounded edit: change one decision at a time (sample rule, estimator command, fixed effects, clustering, export format, or robustness check). Prefer the smallest patch that can pass validation.
- Selection split discipline: treat the user's immediate failure or requested artifact as the selection split. Reserve at least one alternate outcome, sample window, estimator command family, or export target as the held-out gate.
- Held-out gate: define checks before running code:
isid/duplicate status, merge assertions, treatment support, missingness thresholds, expected table/figure files, and one non-focal robustness/specification that the change must not break. - Reject buffer: if a candidate spec fails the gate, log the failure,
.dodiff, and gate output inanalysis_log.mdor the Stata log; revert to the last passing spec and do not retry the same unchecked pattern. - Slow/meta update: at the end of the task, write down
accepted_patternsandrejected_patternsfrom the trajectory. Do not widen the canonical.dotemplate from a single passing run. - Promote only after validation: only turn a one-off fix into reusable
.doboilerplate after it passes the current data and at least one alternate outcome/sample/specification.
Three domain modes (default = AER econ; alternates = epi & ML-causal)
The default playbook above is AER-style applied econometrics — the AEA convention: written-out estimating equation, identifying assumption, design horse-race, full robustness gauntlet. The skill also ships two parallel sub-pipelines for the other two big causal-inference traditions, each reusing the same Steps 1–4 (cleaning / construction / Table 1 / diagnostics) and Step 8 (tables/figures) — only Step 5 (estimator) and Step 6/7 swap commands:
| Mode | Reader convention | Step-5 estimator stack | Reporting stack | Jump to |
|---|---|---|---|---|
| Default — Applied Econ (AER / QJE / AEJ) | "Show the equation + identifying assumption + design horse-race; controls visible; clustered SE" | DID / IV / RD / SCM / matching / reghdfe HDFE | AER house-style multi-column esttab / outreg2 / coefplot + 8-section paper layout | Steps 1 → 8 (entire playbook below) |
| Mode A — Epidemiology / Public Health | "STROBE / TRIPOD-AI; target trial protocol; doubly-robust estimand; absolute & relative risk; KM survival" | Target-trial emulation · IPTW (teffects ipw) · IPWRA / AIPW (teffects ipwra / teffects aipw) · g-formula (gformula) · TMLE (eltmle) · Mendelian randomization (mrrobust IVW / mregger / mrpresso) · KM/Cox/AFT (sts/stcox/streg/strmst2) | Same esttab + risk-difference / hazard-ratio / E-value rows | §A. Epidemiology pipeline |
| Mode B — ML Causal Inference | "DML / meta-learners / causal forest / DR-learner; CATE distribution; policy value" | DML (ddml / pdslasso) · S/T/X/R/DR-Learner (ddml interactive) · GRF causal forest (crforest / cforest) · BART / BCF (external Python via python_user) · matrix completion (external) | esttab ML horse-race + crforest CATE plot + policy-value table | §B. ML causal pipeline |
How to invoke a non-default mode (Claude / agent picks this up from the user's wording):
| User says... | Mode the skill switches to |
|---|---|
| "Run a DID / IV / RD / event study", "AER table", "applied micro" | Default (AER econ) — Steps 1 → 8 |
| "Target trial emulation", "g-formula", "IPTW", "TMLE", "Mendelian randomization", "STROBE / TRIPOD", "公共健康 / 流行病学", "epi pipeline", "RWE study", "cohort study", "case-control" | Mode A (Epi) — §A |
| "DML", "double machine learning", "ddml", "causal forest", "crforest", "meta-learner", "CATE", "policy learning", "ML causal", "因果机器学习" | Mode B (ML causal) — §B |
| "Mix" (e.g. "estimate DID + then ML CATE on the heterogeneity") | Default + Mode B in sequence — every estimator stores results via eststo, drop them all into one esttab for the horse-race column |
The three modes share the same Step 1–4 cleaning / Table 1 / diagnostics scaffolding, the same Step 8 export stack, and the same DAG-first identification logic — switching modes only changes which Step-5 command family you reach for. If you only want descriptive stats / Table 1 / a balance check, the AER tabstat / balancetable / asdoc calls in Step 3 work identically across all three modes.
Stata-specific caveat for Mode B: Stata's first-party ML-causal coverage is thinner than Python/R. For Dragonnet / TARNet / CEVAE / cfcausal / fairness audit, call out to Python via Stata 18's
python:/python scriptblock (or shell out to a sister.py) and read the result back viaframeorimport delimited. The skill prefers native Stata commands (ddml,pdslasso,crforest) where they exist, and explicitly marks the Python callouts in §B.
Default Output Spec — Economics Empirical Paper
This skill defaults to the applied-economics paper convention. Unless the user explicitly asks for a single point estimate, every .do-file run produces the full publication-ready output set below. Treat it as the contract of Step 8 — mandatory, not opt-in.
Required tables (always produced)
| # | Table | Stata source | Saves to |
|---|---|---|---|
| T1 | Summary statistics & balance (treated vs control, with SMD / p-values) | balancetable + asdoc sum (Step 3) | tables/table1_balance.{tex,rtf,xlsx,docx} |
| T2 ★ | Main results — multi-column regression M1→M6 (progressive controls + FE) | eststo 6 specs → esttab (Step 5–6) | tables/table2_main.{tex,rtf,xlsx,docx} |
| T3 | Mechanism / outcome ladder — same treatment, 3+ outcomes side-by-side | loop eststo: reghdfe over outcomes → esttab (Step 7) | tables/table3_mechanism.{tex,rtf,xlsx,docx} |
| T4 | Heterogeneity — subgroup × main coef (gender, age, region, …) | subgroup eststo + suest Wald → esttab (Step 7) | tables/table4_heterogeneity.{tex,rtf,xlsx,docx} |
| T5 | Robustness battery — alt SE / cluster / sample / placebo, in one table | eststo × variants → esttab (Step 6) | tables/table5_robustness.{tex,rtf,xlsx,docx} |
★ Table 2 is the centerpiece of every economics paper. It is the multi-column regression table that walks the reader from raw correlation (M1) to the fully-specified design (M6: 2-way FE + interacted FE + cluster-robust SE). Do not collapse it into a single column. Do not report only the headline coefficient. The progression is the credibility argument: if M1→M6 is monotone and stable, the design is plausibly identifying; if it collapses on adding FE, that is the result.
Canonical 6 columns, in order:
- M1 raw bivariate (
reg y treat)- M2 + demographics (
+ age + edu)- M3 + sector controls (
+ tenure / firm_size)- M4 + unit FE (
reghdfe ..., absorb(unit))- M5 + 2-way FE (
absorb(unit year))- M6 + interacted FE (
absorb(unit year i.industry#i.year)) withvce(cluster unit)
Required figures (always produced)
| # | Figure | Stata source | Saves to |
|---|---|---|---|
| F1 | Trend / motivation — treated vs control over time, with policy line | collapse (mean) y, by(year treat) → twoway line (Step 3) | figures/fig1_trend.pdf (+ .png) |
| F2 | Event-study coefficients with 95% CI, base period at –1 | eventstudyinteract / csdid / coefplot, keep(*.rel) (Step 5) | figures/fig2_event_study.pdf |
| F3 | Coefficient plot across specs M1→M6 | coefplot m1 m2 m3 m4 m5 m6, keep(treat) vertical (Step 8) | figures/fig3_coefplot.pdf |
| F4 | Robustness / sensitivity curve — bacondecomp plot, honestdid plot, or cluster-comparison forest | scenario-specific (Step 6) | figures/fig4_sensitivity.pdf |
Output file layout (default)
project/
├── tables/ table1_balance.{tex,rtf,xlsx,docx} table2_main.{tex,rtf,xlsx,docx}
│ table3_mechanism.{tex,rtf,xlsx,docx} table4_heterogeneity.{tex,rtf,xlsx,docx}
│ table5_robustness.{tex,rtf,xlsx,docx}
└── figures/ fig1_trend.{pdf,png} fig2_event_study.{pdf,png}
fig3_coefplot.{pdf,png} fig4_sensitivity.{pdf,png}
Every table → .tex (LaTeX booktabs) and .rtf (Word) and .xlsx (Excel) and .docx (Word OOXML). Every figure → .pdf (vector for LaTeX) and .png at ≥300 dpi (slides / web).
When to deviate
- Single quick estimate — produce only the relevant cell, but warn that the standard deliverable is the full set above and offer to run it.
- Design does not support a figure (cross-section → no event study) — skip with a printed
displaynote explaining why; do not silently drop. - N=1 treated unit (
synth) — replace F1/F2 with the SCM trajectory + placebo distribution fromsynth_runner; T1–T5 still apply.
Required packages
* Run once on a fresh Stata install:
ssc install reghdfe, replace
ssc install ftools, replace // dependency of reghdfe / ivreg2
ssc install ivreg2, replace
ssc install ranktest, replace // dependency of ivreg2
ssc install ivreghdfe, replace // ivreg2 × reghdfe: high-dim FE IV
ssc install ppmlhdfe, replace // Poisson with HD FE
ssc install csdid, replace // Callaway–Sant'Anna (2021)
ssc install drdid, replace // dependency of csdid
ssc install did_imputation, replace // Borusyak–Jaravel–Spiess (2024)
ssc install eventstudyinteract, replace // Sun & Abraham (2021)
ssc install sdid, replace // Synthetic DID (Arkhangelsky et al. 2021)
ssc install did_multiplegt_dyn, replace // de Chaisemartin & D'Haultfœuille
ssc install bacondecomp, replace // Goodman-Bacon (2021)
ssc install honestdid, replace // Rambachan–Roth (2023) PT sensitivity
ssc install rdrobust, replace // Calonico–Cattaneo–Titiunik RD
ssc install rddensity, replace // McCrary / Cattaneo et al. density test
ssc install synth, replace // Abadie–Diamond–Hainmueller SCM
ssc install synth_runner, replace // SCM with placebos + inference
ssc install psmatch2, replace // propensity-score matching
ssc install ebalance, replace // entropy balancing
ssc install coefplot, replace
ssc install estout, replace // provides estout / esttab / eststo
ssc install outreg2, replace
ssc install asdoc, replace // one-click Word/Excel tables
ssc install binscatter, replace
ssc install balancetable, replace
ssc install winsor2, replace
ssc install xtable, replace // better xtreg output tables
ssc install boottest, replace // wild cluster bootstrap (Roodman et al.)
ssc install ritest, replace // randomization inference
ssc install rwolf, replace // Romano–Wolf multiple-testing
ssc install moremata, replace // Mata extensions (dep for several)
ssc install mdesc, replace // missing data description
ssc install missings, replace // missings dropvars, report
ssc install unique, replace // unique IDs in panel
ssc install schemepack, replace // modern publication themes
The 8 Steps — Canonical Pipeline (mapped to AER paper sections)
┌──────────────────────────────────────────────────────────────────────┐
│ Step −1 Pre-Analysis Plan (PAP) power/sampsi/clustersampsi/MDE │
│ Step 0 Sample log + data contract sample_log/assert/xtdescribe/JSON │
│ Step 1 Data import & cleaning use/import/destring/misstable/merge│
│ Step 2 Variable construction gen/egen/winsor2/xtile/xtset/L.F.D.│
│ Step 2.5 Empirical strategy equation × ID assumption + pre-reg │
│ Step 3 Descriptive statistics tabstat/balancetable/asdoc/pwcorr │
│ Step 3.5 Identification graphics event-study/1st-stage/McCrary/love │
│ Step 4 Diagnostic tests sktest/hettest/xtserial/vif/dfuller│
│ Step 5 Baseline modeling reghdfe/ivreg2/csdid/rdrobust/synth│
│ Step 6 Robustness battery bacondecomp/honestdid/rwolf/boottest│
│ Step 7 Further analysis triple-diff/subgroup/medsem/margins│
│ Step 8 Tables & figures esttab/outreg2/coefplot/rdplot │
└──────────────────────────────────────────────────────────────────────┘
The 8 steps mirror the canonical sections of an applied AER / QJE / AEJ paper. Each step is one paper section and emits a paper-ready artifact on disk:
Paper section Step Stata moves
─────────────────────────── ───── ────────────────────────────────────────────────
Pre-Analysis Plan −1 power/sampsi + freeze protocol.do to disk
§1. Data 0 sample_log + 5-check data contract → JSON
§1. Data 1 use/import/destring/misstable/merge assert/xtset
§1. Data 2 gen/egen/winsor2/xtile/L./F./D./CPI deflation
§1.1 Descriptives (Table 1) 3 tabstat · balancetable · asdoc · pwcorr · twoway
§2. Empirical Strategy 2.5 write equation + ID assumption → strategy.do
§3. Identification graphics 3.5 event-study · 1st-stage F · McCrary · love · SCM
§3.5 Diagnostics 4 swilk · hettest · xtserial · vif · dfuller · hausman
§4. Main Results (Table 2) 5 M1→M6 progressive controls + FE (eststo + esttab)
§5. Heterogeneity (Table 3) 7 margins/marginsplot · subgroup · medsem
§6. Mechanisms / Channels 7 medsem/khb · outcome ladder · DDD interactions
§7. Robustness gauntlet 6 bacondecomp · honestdid · psacalc · boottest · ritest · rwolf
§8. Replication package 8 esttab + outreg2 + coefplot + reproducibility stamp
Below is the canonical command at each step. All examples share one running narrative — a labor-economics panel where training (treatment) affects log_wage (outcome), with covariates age, edu, tenure, panel keys worker_id / firm_id / year. Variable names and parameter values are illustrative; substitute the real ones from the user's dataset. Only command names and option shapes are normative.
When a step has many variants (e.g. staggered DID has 5 estimators; heteroskedasticity has 4 classic tests), SKILL.md shows the one you reach for first and links to
references/NN-<topic>.mdfor the rest. Read the reference file when the user's case doesn't fit the default.
Paper-ready figure & table inventory (what to produce by section)
A modern AER paper has 5–7 figures and 3–5 main tables + an appendix robustness table. Every step below leaves at least one numbered artifact on disk. Default file names assume parallel .tex / .rtf exports (the agent should produce both so co-authors can edit in Word, and the build system can use LaTeX):
| § | Artifact | Stata primitive | Filenames |
|---|---|---|---|
| §1 | Figure 1: raw trends / treatment rollout | collapse + twoway line · heatplot for staggered rollout | figures/fig1_trend.{pdf,png} |
| §1 | Table 1: summary stats (full / treated / control + Δ + SMD) | balancetable · asdoc sum, by() · tabstat | tables/table1_balance.{tex,rtf,xlsx,docx} |
| §3 | Figure 2: identification graphic (event-study / first-stage / McCrary / RD scatter / SCM trajectory) | coefplot after eventstudyinteract/csdid · binscatter · rdplot · rddensity, plot · synth | figures/fig2_event_study.{pdf,png} |
| §4 | Table 2: main results — progressive controls M1→M6 | eststo 6 specs → esttab | tables/table2_main.{tex,rtf,xlsx,docx} |
| §4 | Table 2-bis: design horse-race (OLS / IV / DID / matching) | eststo mix + esttab | tables/table2b_designs.{tex,rtf,xlsx,docx} |
| §4 | Figure 3: coefficient plot across specs | coefplot m1 m2 m3 m4 m5 m6, keep(treat) | figures/fig3_coefplot.{pdf,png} |
| §5 | Table 3: heterogeneity by subgroup | eststo per slice + esttab + suest Wald | tables/table3_heterogeneity.{tex,rtf,xlsx,docx} |
| §5 | Figure 4: dose-response / margins-by-quartile | xtile + margins + marginsplot | figures/fig4_dose.{pdf,png} |
| §6 | Table 4: mechanism / outcome ladder | loop eststo: reghdfe over outcomes → esttab | tables/table4_mechanism.{tex,rtf,xlsx,docx} |
| §7 | Table A1: robustness master (one column per check) | eststo × variants → esttab | tables/tableA1_robustness.{tex,rtf,xlsx,docx} |
| §7 | Figure 5: spec curve — coefficient + 95% CI across all specs | hand-rolled spec loop + twoway rcap | figures/fig5_spec_curve.{pdf,png} |
| §7 | Figure 6: sensitivity (HonestDiD / Oster / E-value) | honestdid, coefplot · psacalc plot · evalue table | figures/fig6_sensitivity.{pdf,png} |
| §8 | Replication bundle: all tables in one document | esttab ..., append to one .tex / .rtf · texdoc | replication/paper_tables.{tex,rtf,xlsx,docx} |
Every Stata estimator above stores results via
eststoand can be passed straight intoesttab/coefplot/outreg2. Don't hand-roll LaTeX, and don't render Word fromoutsheet/putexcelmatrices —esttabandoutreg2apply book-tab borders, AER-style stars, and the right SE label automatically. For deeper export recipes (LaTeX / Word / Markdown variants,texdoc,frmttable), seereferences/08-tables-plots.md.
Export cookbook — LaTeX / Word / RTF in one block
Stata's export stack is more fragmented than Python's StatsPAI. Three tiers, picked by scope:
| Tier | Use when | API | Hot options |
|---|---|---|---|
| 1. Single multi-column table | Exporting one Table 2 / Table 3 / Table A1 with progressive columns | .tex / .rtf: esttab with booktabs.xlsx / .docx: outreg2 (esttab's native Office export is a data dumper, not a publication formatter — outreg2 produces properly formatted Word/Excel with borders, aligned stars, and AER-style layout) | esttab for tex/rtf: keep(), drop(), mtitles(), stats(N r2 r2_a, labels(...)), star(* 0.10 ** 0.05 *** 0.01), label, booktabs, addnotes().outreg2 for xlsx/docx: label dec(3), addtext() for FE indicators, replace first / append subsequent columns.Always emit all four formats — esttab for tex/rtf in a foreach ext in tex rtf loop, outreg2 for xlsx/docx in a separate foreach ext in xlsx docx loop. |
| 2. Multi-panel paper format (Tables 2 + 3 + A1 + A2 in one file) | Producing the paper-tables block — main + heterogeneity + robustness + placebo as a single document | esttab ... using "paper.tex", replace for first panel; subsequent esttab ... using "paper.tex", append for each next panel; texdoc init "paper.tex" for full LaTeX with prose. Repeat for .rtf/.xlsx/.docx bundles. | first panel: replace; subsequent: append; surround with texdoc for headings |
3. Full session bundle (the Stata 17+ collect equivalent) | Replication appendix that mixes summary stats + balance + multiple regression tables + headings + prose in one file | collect create papercollect get summary, ...collect get est ...collect layout ...collect export "paper.xlsx" (also .docx/.html/.tex/.md) | Stata 17+ only; for older Stata use texdoc / markdoc |
Journal styling — pick the right star levels and SE label. The AEA convention is * 0.10 ** 0.05 *** 0.01 and SE label "Standard errors in parentheses"; QJE / Econometrica / RES variants only differ in stars / notes / fonts. Define an esttab wrapper once at the top of the do-file:
* Top of master.do — journal house-style wrapper
local AER_STAR "* 0.10 ** 0.05 *** 0.01"
local AER_NOTES "Cluster-robust standard errors in parentheses. * p<0.10, ** p<0.05, *** p<0.01."
local AER_STATS stats(N r2_a, labels("N" "Adj. R²"))
* LaTeX + RTF via esttab (booktabs for tex)
* esttab m1 m2 m3 using "tables/table2.tex", replace ///
* se star(`AER_STAR') label booktabs `AER_STATS' addnotes(`AER_NOTES')
* esttab m1 m2 m3 using "tables/table2.rtf", replace ///
* se star(`AER_STAR') label `AER_STATS' addnotes(`AER_NOTES')
* Excel + Word via outreg2 (publication-grade Office formatting)
* First column: replace; subsequent: append
* outreg2 using "tables/table2.xlsx", replace label dec(3) ///
* keep(training age edu tenure) addtext(Worker FE, Yes, Year FE, Yes)
* outreg2 using "tables/table2.xlsx", append label dec(3) ///
* keep(training age edu tenure region) addtext(Worker FE, Yes, Year FE, Yes, Region, Yes)
Multi-format export pattern — emit .tex and .rtf via esttab, then .xlsx and .docx via outreg2. Never use esttab ... using "... .xlsx" or esttab ... using "... .docx" — esttab's native Office export is a raw data dumper, not a publication formatter:
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 4k
- Forks
- 476
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
full-empirical-analysis-skill-stata- Source
- github.com/brycewang-stanford/auto-empirical-research-skills