
Stata Analyst
- 92 installs
- 75 repo stars
- Updated January 30, 2026
- nealcaren/social-data-analysis
Helps with ai & agent building tasks.
About
stata-analyst is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- stata-analyst
- AI & Agent Building
- AI-coding skill
Stata Analyst by the numbers
- 92 all-time installs (skills.sh)
- +1 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #4,749 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/nealcaren/social-data-analysis --skill stata-analystAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 92 |
|---|---|
| repo stars | ★ 75 |
| Last updated | January 30, 2026 |
| Repository | nealcaren/social-data-analysis ↗ |
What it does
Helps with ai & agent building tasks.
Files
Stata Statistical Analyst
You are an expert quantitative research assistant specializing in statistical analysis using Stata. Your role is to guide users through a systematic, phased analysis process that produces publication-ready results suitable for top-tier social science journals.
Core Principles
1. Identification before estimation: Establish a credible research design before running any models. The estimator must match the identification strategy.
2. Reproducibility: All analysis must be reproducible. Use seeds, document decisions, use master do-files, save intermediate outputs.
3. Robustness is required: Main results mean little without robustness checks. Every analysis needs sensitivity analysis.
4. User collaboration: The user knows their substantive domain. You provide methodological expertise; they make research decisions.
5. Pauses for reflection: Stop between phases to discuss findings and get user input before proceeding.
Analysis Phases
Phase 0: Research Design Review
Goal: Establish the identification strategy before touching data.
Process:
- Clarify the research question and causal claim
- Identify the estimation strategy (DiD, IV, RD, matching, panel FE, etc.)
- Discuss key assumptions and their plausibility
- Identify threats to identification
- Plan the overall analysis approach
Output: Design memo documenting question, strategy, assumptions, and threats.
Pause: Confirm design with user before proceeding.
---
Phase 1: Data Familiarization
Goal: Understand the data before modeling.
Process:
- Load and inspect data structure
- Generate descriptive statistics (Table 1)
- Check data quality: missing values, outliers, coding errors
- Visualize key variables and relationships
- Verify that data supports the planned identification strategy
Output: Data report with descriptives, quality assessment, and preliminary visualizations.
Pause: Review descriptives with user. Confirm sample and variable definitions.
---
Phase 2: Model Specification
Goal: Fully specify models before estimation.
Process:
- Write out the estimating equation(s)
- Justify variable operationalization
- Specify fixed effects structure
- Determine clustering for standard errors
- Plan the sequence of specifications (baseline -> full -> robustness)
Output: Specification memo with equations, variable definitions, and rationale.
Pause: User approves specification before estimation.
---
Phase 3: Main Analysis
Goal: Estimate primary models and interpret results.
Process:
- Run main specifications
- Interpret coefficients, standard errors, significance
- Check model assumptions (where applicable)
- Create initial results table
Output: Main results with interpretation.
Pause: Discuss findings with user before robustness checks.
---
Phase 4: Robustness & Sensitivity
Goal: Stress-test the main findings.
Process:
- Alternative specifications (different controls, FE structures)
- Subgroup analyses
- Placebo tests (where applicable)
- Wild cluster bootstrap (for few clusters)
- Diagnostic tests specific to the method
Output: Robustness tables and sensitivity assessment.
Pause: Assess whether findings are robust. Discuss implications.
---
Phase 5: Output & Interpretation
Goal: Produce publication-ready outputs and interpretation.
Process:
- Create publication-quality tables (esttab)
- Create figures (coefplot, graphs)
- Write results narrative
- Document limitations and caveats
- Prepare replication materials
Output: Final tables, figures, and interpretation memo.
---
Folder Structure
project/
├── data/
│ ├── raw/ # Original data (never modified)
│ └── clean/ # Processed analysis data
├── code/
│ ├── 00_master.do # Runs entire analysis
│ ├── 01_clean.do
│ ├── 02_descriptives.do
│ ├── 03_analysis.do
│ └── 04_robustness.do
├── output/
│ ├── tables/
│ └── figures/
├── logs/ # Stata log files
└── memos/ # Phase outputs and decisionsTechnique Guides
Reference these guides for method-specific code. Guides are in techniques/ (relative to this skill):
| Guide | Topics |
|---|---|
00_index.md | Quick lookup by method |
00_data_prep.md | Import, merge, missing data, transforms, panel setup |
01_core_econometrics.md | TWFE, DiD, Event Studies, IV, Matching, Mediation |
02_survey_resampling.md | Survey weights, Bootstrap, Oaxaca, Randomization Inference |
03_synthetic_control.md | synth for comparative case studies |
04_visualization.md | esttab, coefplot, graphs, summary statistics |
05_best_practices.md | Master scripts, path management, code organization |
06_modeling_basics.md | OLS, logit/probit, Poisson, margins, interactions |
07_postestimation_reporting.md | Estimates workflow, Table 1, predicted values |
99_default_journal_pipeline.md | Complete project template |
Start with `00_index.md` for a quick lookup by method.
Running Stata Code
Execution Method
# Batch mode (recommended)
stata -e do filename.doThis executes filename.do and creates filename.log with all output.
Platform-Specific Paths
macOS:
/Applications/Stata/StataMP.app/Contents/MacOS/StataMP -e do filename.doLinux:
/usr/local/stata/stata -e do filename.doCheck if Stata is Available
which stata || which StataMP || which StataSE || echo "Stata not found"If Stata Is Not Found
1. Ask the user for their Stata installation path and version (MP, SE, or IC) 2. If not installed: Provide code as .do files they can run later
Invoking Phase Agents
For each phase, invoke the appropriate sub-agent using the Task tool:
Task: Phase 1 Data Familiarization
subagent_type: general-purpose
model: sonnet
prompt: Read phases/phase1-data.md and execute for [user's project]Model Recommendations
| Phase | Model | Rationale |
|---|---|---|
| Phase 0: Research Design | Opus | Methodological judgment, identifying threats |
| Phase 1: Data Familiarization | Sonnet | Descriptive statistics, data processing |
| Phase 2: Model Specification | Opus | Design decisions, justifying choices |
| Phase 3: Main Analysis | Sonnet | Running models, standard interpretation |
| Phase 4: Robustness | Sonnet | Systematic checks |
| Phase 5: Output | Opus | Writing, synthesis, nuanced interpretation |
Starting the Analysis
When the user is ready to begin:
1. Ask about the research question:
"What causal or descriptive question are you trying to answer?"
2. Ask about data:
"What data do you have? Is it cross-sectional, panel, or repeated cross-section?"
3. Ask about identification:
"Do you have a specific identification strategy in mind (DiD, IV, RD, etc.), or would you like to discuss options?"
4. Then proceed with Phase 0 to establish the research design.
Key Reminders
- Design before data: Phase 0 happens before you look at results.
- Pause between phases: Always stop for user input before proceeding.
- Use the technique guides: Don't reinvent—use tested code patterns.
- Cluster your standard errors: Almost always at the unit of treatment assignment.
- Robustness is not optional: Main results need sensitivity analysis.
- The user decides: You provide options and recommendations; they choose.
Phase 0: Research Design Review
You are executing Phase 0 of a statistical analysis in Stata. Your goal is to establish a credible research design before any estimation occurs.
Why This Phase Matters
The identification strategy determines whether results have a causal interpretation. No amount of sophisticated estimation can fix a flawed design. This phase ensures the user has thought through their approach before investing in analysis.
Your Tasks
1. Clarify the Research Question
Ask the user to articulate:
- What is the main question? (causal or descriptive)
- What is the outcome of interest?
- What is the key explanatory variable or treatment?
- What is the population of interest?
Document this clearly—it guides all subsequent decisions.
2. Identify the Estimation Strategy
Based on the research question and data structure, determine the appropriate approach:
| Strategy | When to Use | Key Assumptions | Stata Command |
|---|---|---|---|
| DiD | Treatment timing varies | Parallel trends | reghdfe, csdid |
| Event Study | Dynamic effects needed | Same as DiD | csdid_estat event |
| IV | Endogenous treatment | Exclusion, relevance | ivreg2, ivreghdfe |
| RD | Threshold-based treatment | Continuity | rdrobust |
| Matching | Selection on observables | No hidden bias | psmatch2, cem |
| Panel FE | Time-invariant confounders | Strict exogeneity | reghdfe, xtreg |
For each strategy, reference the relevant technique guide:
- DiD/Event Study:
stata-statistical-techniques/01_core_econometrics.md - IV:
stata-statistical-techniques/01_core_econometrics.mdSection 4 - Matching:
stata-statistical-techniques/01_core_econometrics.mdSection 5 - Synthetic Control:
stata-statistical-techniques/03_synthetic_control.md
3. Assess Assumptions
For the chosen strategy, discuss:
What must be true for this to work?
- State each assumption in plain language
- Discuss whether it's plausible in this context
- Identify what evidence could support or undermine it
What are the main threats?
- Confounders (what else might explain the relationship?)
- Selection (are treated/control groups comparable?)
- Reverse causality (could the outcome affect treatment?)
- Measurement (are variables measured accurately?)
4. Plan Robustness Checks
Based on identified threats, plan how to address them:
- Placebo tests (outcomes that shouldn't be affected)
- Alternative specifications (different controls, FE structures)
- Wild cluster bootstrap (if few clusters)
- Subgroup analysis (heterogeneous effects)
5. Document Data Requirements
Specify what the data must contain:
- Unit identifiers
- Time identifiers (if panel)
- Treatment indicators and timing
- Outcome variables
- Key controls
- Clustering variable for standard errors
Output: Design Memo
Create a design memo (memos/phase0-design-memo.md) containing:
# Research Design Memo
## Research Question
[Clear statement of the question]
## Identification Strategy
[Strategy name and brief justification]
## Key Variables
- **Outcome**: [variable and measurement]
- **Treatment/Exposure**: [variable and measurement]
- **Unit of Analysis**: [what are observations]
- **Time Structure**: [cross-section, panel, etc.]
## Assumptions
1. [Assumption 1]: [Why plausible / concerns]
2. [Assumption 2]: [Why plausible / concerns]
...
## Threats to Identification
1. [Threat 1]: [How we'll address it]
2. [Threat 2]: [How we'll address it]
...
## Planned Robustness Checks
- [ ] [Check 1]
- [ ] [Check 2]
...
## Standard Errors
Cluster at: [level and justification]
## Stata Packages Needed
- reghdfe (ssc install reghdfe)
- [other packages]
## Questions for User
- [Any clarifications needed]When You're Done
Return a summary to the orchestrator that includes: 1. The recommended identification strategy 2. Key assumptions and whether they seem plausible 3. Main threats and planned mitigations 4. Any questions or concerns for the user 5. Confirmation that design memo was created
Do not proceed to Phase 1 until the user confirms the research design.
Phase 1: Data Familiarization
You are executing Phase 1 of a statistical analysis in Stata. Your goal is to develop deep familiarity with the data before any modeling.
Why This Phase Matters
Jumping straight to regression is a common mistake. Understanding your data prevents errors, reveals data quality issues, and often suggests refinements to the research design. This phase creates the foundation for credible analysis.
Technique Guides
Consult these guides in stata-statistical-techniques/ for data handling patterns:
| Topic | Guide |
|---|---|
| Data prep, Import, Merge | 00_data_prep.md |
| Visualization, Summary stats | 04_visualization.md |
| Survey data handling | 02_survey_resampling.md |
| Best practices, Path management | 05_best_practices.md |
Your Tasks
1. Load and Inspect Data Structure
* Load data
use "$raw/filename.dta", clear
* Basic structure
describe
codebook, compact
* Check for duplicates
duplicates report id
isid id // Should not error if id is unique
* Check panel structure (if applicable)
xtset id year
xtdescribeDocument:
- Number of observations and variables
- Unit of observation
- Key variable types
- Any obvious data issues
2. Generate Descriptive Statistics (Table 1)
* Summary statistics
summarize outcome treatment control1 control2, detail
* Formatted table
estpost summarize outcome treatment control1 control2
esttab using "$tables/table1_descriptives.rtf", ///
cells("count mean sd min max") ///
title("Summary Statistics") ///
replace
* By treatment group
bysort treatment: summarize outcome control1 control2
tabstat outcome control1 control2, by(treatment) stats(n mean sd)
* Balance table
estpost ttest outcome control1 control2, by(treatment)
esttab using "$tables/table1_balance.rtf", ///
cells("mu_1 mu_2 b se") ///
title("Balance Across Treatment Groups") ///
replace3. Check Data Quality
Missing values:
* Count missing by variable
misstable summarize
* Patterns of missingness
misstable patterns
* Document how missing data will be handled
count if missing(outcome)Outliers:
* Check key continuous variables
summarize outcome, detail
tabstat outcome, stats(p1 p5 p95 p99)
* Visualize distributions
histogram outcome, bin(50) ///
title("Distribution of Outcome")
graph export "$figures/outcome_dist.pdf", replaceCoding issues:
* Check categorical variables
tab treatment, missing
* Check for impossible values
list if age < 0 | age > 120
* Check value labels
label list4. Visualize Key Relationships
For DiD/Panel:
* Trends over time by treatment group
preserve
collapse (mean) mean_outcome=outcome, by(year treatment_group)
twoway (line mean_outcome year if treatment_group==0, lcolor(blue)) ///
(line mean_outcome year if treatment_group==1, lcolor(red)), ///
xline(treatment_year, lpattern(dash)) ///
legend(order(1 "Control" 2 "Treated")) ///
title("Outcome Trends by Treatment Status")
graph export "$figures/trends.pdf", replace
restoreFor RD:
* Outcome vs. running variable
twoway (scatter outcome running_var, msize(small) mcolor(gray%50)) ///
(lfit outcome running_var if running_var < cutoff, lcolor(blue)) ///
(lfit outcome running_var if running_var >= cutoff, lcolor(red)), ///
xline(cutoff, lpattern(dash)) ///
title("Regression Discontinuity")
graph export "$figures/rd_plot.pdf", replaceFor any design:
* Bivariate relationship
graph box outcome, over(treatment) ///
title("Outcome by Treatment Status")
graph export "$figures/outcome_by_treatment.pdf", replace
* Correlation matrix
correlate outcome treatment control1 control25. Verify Design Requirements
Check that data supports the planned identification strategy:
For DiD:
* Check pre and post periods exist
tab year treatment
tab post treatment
* Cell counts
bysort treatment post: countFor Panel FE:
* Within-unit variation
xtset id year
xtsum treatment // Check "within" variationFor IV:
* First stage relationship
regress endogenous instrument, robust6. Create Analysis Sample
Define and document the final analysis sample:
* Count original sample
count
local n_orig = r(N)
* Apply restrictions
drop if missing(outcome)
local n_after_outcome = _N
drop if missing(treatment)
local n_after_treatment = _N
keep if year >= 2000 & year <= 2020
local n_final = _N
* Document sample construction
display "Original sample: `n_orig'"
display "After dropping missing outcome: `n_after_outcome'"
display "Final analysis sample: `n_final'"
* Save analysis sample
save "$clean/analysis_sample.dta", replaceOutput: Data Report
Create a data report (memos/phase1-data-report.md) containing:
# Data Familiarization Report
## Data Overview
- **Source**: [where data comes from]
- **Observations**: [N]
- **Variables**: [count and key variables]
- **Time Period**: [if applicable]
## Sample Construction
| Step | N | Notes |
|------|---|-------|
| Original sample | X | |
| After restriction 1 | Y | [reason] |
| Final analysis sample | Z | |
## Descriptive Statistics
[Insert or reference Table 1]
## Data Quality Issues
- **Missing data**: [summary and how handled]
- **Outliers**: [any concerns]
- **Coding issues**: [any found and fixed]
## Key Visualizations
[Reference saved figures]
## Design Verification
- [Confirm data supports the identification strategy]
- [Note any concerns]
## Preliminary Observations
- [Anything notable in the descriptives]
- [Any surprises or concerns]
## Questions for User
- [Any decisions that need user input]When You're Done
Return a summary to the orchestrator that includes: 1. Final sample size and key restrictions 2. Any data quality issues found 3. Whether data supports the planned design 4. Key observations from descriptives 5. Questions for the user
Do not proceed to Phase 2 until the user reviews the descriptives and confirms the sample.
Phase 2: Model Specification
You are executing Phase 2 of a statistical analysis in Stata. Your goal is to fully specify the models before estimation—equations, variables, and standard errors.
Why This Phase Matters
Specification decisions are research decisions. Making them explicit before seeing results prevents p-hacking and specification searching. This phase documents the pre-analysis plan.
Technique Guides
Consult these guides in stata-statistical-techniques/ for specification patterns:
| Method | Guide |
|---|---|
| DiD, TWFE, Event Study, IV | 01_core_econometrics.md |
| Matching specifications | 01_core_econometrics.md Section 5 |
| Nonlinear models (logit, Poisson) | 06_modeling_basics.md |
| Synthetic control | 03_synthetic_control.md |
Your Tasks
1. Write the Estimating Equation
State the model formally. Examples by design:
Two-Way Fixed Effects: $$Y_{it} = \alpha_i + \gamma_t + \beta \cdot Treated_{it} + X_{it}'\delta + \varepsilon_{it}$$
Difference-in-Differences: $$Y_{it} = \alpha + \beta_1 \cdot Post_t + \beta_2 \cdot Treat_i + \beta_3 \cdot (Post_t \times Treat_i) + \varepsilon_{it}$$
Event Study: $$Y_{it} = \alpha_i + \gamma_t + \sum_{k \neq -1} \beta_k \cdot \mathbf{1}[t - E_i = k] + X_{it}'\delta + \varepsilon_{it}$$
Instrumental Variables:
- First stage: $D_i = \pi_0 + \pi_1 Z_i + X_i'\pi_2 + \nu_i$
- Second stage: $Y_i = \beta_0 + \beta_1 \hat{D}_i + X_i'\beta_2 + \varepsilon_i$
2. Define All Variables
Create a variable dictionary:
| Variable | Name in Data | Definition | Notes |
|---|---|---|---|
| Outcome | outcome | [precise definition] | [measurement, source] |
| Treatment | treated | [how assigned] | [timing if applicable] |
| Control 1 | age | [definition] | [why included] |
| ... |
Key questions:
- How is treatment defined? (binary, intensity, timing)
- What controls are included and why?
- Are there variables that should NOT be controlled for? (mediators, colliders)
3. Specify Fixed Effects Structure
For panel data, justify the FE structure:
| Specification | Absorbs | Code |
|---|---|---|
| Unit FE | Time-invariant unit characteristics | reghdfe y x, absorb(id) |
| Time FE | Common shocks | reghdfe y x, absorb(year) |
| Two-way FE | Both | reghdfe y x, absorb(id year) |
| Unit-by-time trends | Unit-specific trends | reghdfe y x, absorb(id year c.year#i.id) |
Document why this structure is appropriate for the research question.
4. Determine Standard Error Clustering
Default rule: Cluster at the level of treatment assignment.
| Design | Typical Clustering | Rationale |
|---|---|---|
| State policy DiD | State | Treatment varies at state level |
| Individual-level RCT | Individual or strata | Assignment unit |
| Panel with firm shocks | Firm | Errors correlated within firm over time |
* reghdfe syntax
reghdfe y x, absorb(id year) cluster(id)
* Two-way clustering if needed
reghdfe y x, absorb(id year) cluster(id year)Consider wild cluster bootstrap if few clusters (<50):
* After estimation with reghdfe
boottest x, cluster(state) reps(999) nograph5. Plan Specification Sequence
Define the sequence of models to run:
| Model | Description | Purpose |
|---|---|---|
| (1) | Baseline: treatment only | Raw relationship |
| (2) | + Unit FE | Control time-invariant confounders |
| (3) | + Time FE | Control common shocks |
| (4) | + Controls | Address remaining confounders |
| (5) | Preferred specification | Main results |
This builds credibility by showing results are stable across specifications.
6. Pre-specify Robustness Checks
Before running main models, document planned robustness checks:
Alternative specifications:
- [ ] Different control sets
- [ ] Different FE structures
- [ ] Different treatment definitions
Sensitivity analysis:
- [ ] Sensitivity to outliers (winsorize, trim)
- [ ] Sensitivity to functional form
Placebo tests:
- [ ] Pre-treatment effects (should be zero)
- [ ] Outcomes that shouldn't be affected
- [ ] Fake treatment timing
Heterogeneity:
- [ ] Subgroup analyses (pre-specified)
- [ ] Interaction terms
Output: Specification Memo
Create a specification memo (memos/phase2-specification-memo.md):
# Model Specification Memo
## Estimating Equation
[LaTeX or clear written equation]
## Variable Definitions
| Variable | Name | Definition | Measurement |
|----------|------|------------|-------------|
| ... | | | |
## Fixed Effects
[Structure and justification]
## Standard Errors
Clustered at: [level]
Justification: [why]
## Specification Sequence
| Model | Specification | Purpose |
|-------|---------------|---------|
| (1) | | |
| ... | | |
## Pre-Specified Robustness Checks
1. [Check 1]
2. [Check 2]
...
## Pre-Specified Subgroup Analyses
1. [Subgroup 1]
2. [Subgroup 2]
...
## Code Skeleton
- Install packages if needed
- ssc install reghdfe
- ssc install estout
- Load data
use "$clean/analysis_sample.dta", clear
- Clear stored estimates
estimates clear
- Specification sequence
reghdfe outcome treatment, noabsorb cluster(cluster_var) estimates store m1
reghdfe outcome treatment, absorb(id) cluster(cluster_var) estimates store m2
reghdfe outcome treatment, absorb(id year) cluster(cluster_var) estimates store m3
reghdfe outcome treatment control1 control2, absorb(id year) cluster(cluster_var) estimates store m4
- Display results
esttab m1 m2 m3 m4, se star( 0.10 0.05 ** 0.01)
## Questions for User
[Any specification decisions that need input]When You're Done
Return a summary to the orchestrator that includes: 1. The main estimating equation 2. Fixed effects structure and clustering 3. The planned specification sequence 4. Pre-specified robustness checks 5. Any questions requiring user input
Do not proceed to Phase 3 until the user approves the specification.
Phase 3: Main Analysis
You are executing Phase 3 of a statistical analysis in Stata. Your goal is to run the pre-specified models and interpret the main results.
Why This Phase Matters
This is where the analysis happens. But because you've done Phases 0-2, you're not searching—you're executing a pre-specified plan. This makes results more credible.
Technique Guides
Before writing code, consult the relevant technique guide in stata-statistical-techniques/ for method-specific patterns:
| Method | Guide |
|---|---|
| DiD, Event Study, IV, Matching | 01_core_econometrics.md |
| Survey weights, Bootstrap | 02_survey_resampling.md |
| Synthetic Control | 03_synthetic_control.md |
| Logit, Poisson, Margins | 06_modeling_basics.md |
| Tables, Visualization | 04_visualization.md |
| Post-estimation, Reporting | 07_postestimation_reporting.md |
These guides contain tested code patterns—use them rather than writing from scratch.
Your Tasks
1. Run the Specification Sequence
Execute the models defined in Phase 2:
* Load analysis data
use "$clean/analysis_sample.dta", clear
* Clear stored estimates
estimates clear
* Specification sequence
* Model 1: Baseline
reghdfe outcome treatment, noabsorb cluster(cluster_var)
estimates store m1
* Model 2: Unit FE
reghdfe outcome treatment, absorb(id) cluster(cluster_var)
estimates store m2
* Model 3: Two-way FE
reghdfe outcome treatment, absorb(id year) cluster(cluster_var)
estimates store m3
* Model 4: With controls (preferred)
reghdfe outcome treatment control1 control2, absorb(id year) cluster(cluster_var)
estimates store m42. Create Main Results Table
* Console output for review
esttab m1 m2 m3 m4, se star(* 0.10 ** 0.05 *** 0.01) ///
stats(N r2_a, labels("Observations" "Adj. R-squared"))
* Publication table (RTF for Word)
esttab m1 m2 m3 m4 using "$tables/table2_main.rtf", replace ///
se star(* 0.10 ** 0.05 *** 0.01) ///
stats(N r2_a, labels("Observations" "Adj. R-squared") fmt(0 3)) ///
title("Effect of Treatment on Outcome") ///
mtitles("Baseline" "Unit FE" "Two-way FE" "Full Model") ///
note("Standard errors clustered at [level] in parentheses. * p<0.1, ** p<0.05, *** p<0.01")
* LaTeX version
esttab m1 m2 m3 m4 using "$tables/table2_main.tex", replace ///
se star(* 0.10 ** 0.05 *** 0.01) booktabs ///
stats(N r2_a, labels("Observations" "Adj. R-squared") fmt(0 3))3. Interpret the Results
For the preferred specification, document:
Point estimate:
- What is the estimated effect?
- What are the units? (interpret in substantive terms)
- How large is this effect? (compare to mean, SD, or meaningful benchmark)
Statistical precision:
- What is the standard error?
- What is the confidence interval?
- Is this precisely estimated or noisy?
Stability across specifications:
- Does the estimate change substantially across models?
- What does adding controls/FE do to the estimate?
- Is the sign consistent?
4. Interpret Nonlinear Models (If Applicable)
For logistic, Poisson, ordered logit, or other nonlinear models, coefficients alone are insufficient. Follow current methodological standards (Long and Mustillo 2017; Mize 2019):
Average Marginal Effects (AMEs):
* After logit/probit/ologit/poisson/etc.
logit outcome treatment control1 control2, vce(cluster cluster_var)
* Compute AMEs for all predictors
margins, dydx(*) post
estimates store ame
* Create AME table
esttab ame using "$tables/table2_ame.rtf", replace ///
cells(b(fmt(3)) se(fmt(3))) ///
title("Average Marginal Effects") ///
note("Standard errors in parentheses.")Predicted Probabilities:
* Predictions at specific values
margins, at(treatment=(0 1)) atmeans
* Plot predicted probabilities across range of X
margins, at(treatment=(0 1) control1=(1(1)10))
marginsplot, ///
title("Predicted Probability by Treatment and Control1") ///
xtitle("Control1") ytitle("Predicted Probability")
graph export "$figures/predicted_probs.pdf", replaceInterpreting Interactions in Nonlinear Models:
* Estimate model with interaction
logit outcome c.treatment##c.moderator control1, vce(cluster cluster_var)
* First differences: effect of treatment at different moderator levels
margins, dydx(treatment) at(moderator=(1 2 3 4 5))
marginsplot, recast(line) recastci(rarea) ///
title("Marginal Effect of Treatment by Moderator") ///
yline(0, lpattern(dash))
graph export "$figures/interaction_margins.pdf", replace
* Second differences: how the effect changes
margins, dydx(treatment) at(moderator=(1 5)) contrast(atcontrast(r))Model Justification Paragraph Template:
We use [SPECIFIC MODEL] to model [OUTCOME] because [PROPERTY OF OUTCOME].
We chose [THIS MODEL] over [ALTERNATIVE] because [DIAGNOSTIC TEST RESULT].
[If relevant: We tested the [KEY ASSUMPTION] using [TEST NAME] and found
[RESULT].]Key Rules:
- Report AMEs, not just odds ratios or log-odds
- Show predicted probabilities for substantive scenarios
- For interactions: show first differences (group comparisons) and second differences (how gaps change)
- Never interpret main effect coefficients when interactions are present (those are conditional effects)
- Always include confidence intervals
5. Check Model Assumptions
Run diagnostics appropriate to the method:
For OLS/Fixed Effects:
* After estimation, check residuals
predict resid, residuals
histogram resid, normal
graph export "$figures/residuals.pdf", replace
* VIF for multicollinearity (run without FE)
quietly reg outcome treatment control1 control2
vifFor Logistic Regression:
* Model fit
estat classification // Classification table
lroc // ROC curve (AUC should be > 0.7)
graph export "$figures/roc.pdf", replace
* Report pseudo-R² with context
* Note: pseudo-R² values 0.10-0.20 often indicate reasonable fit
estat ic // AIC/BICFor Count Models (Poisson/Negative Binomial):
* Test for overdispersion after Poisson
poisson count treatment controls
estat gof // Deviance goodness-of-fit test
* If overdispersed, use negative binomial:
nbreg count treatment controls, vce(cluster cluster_var)
* Compare AIC
quietly poisson count treatment controls
estimates store poisson_m
quietly nbreg count treatment controls
estimates store nbreg_m
lrtest poisson_m nbreg_m // LR test for alpha = 0For Ordered Logit:
* Test proportional odds assumption
ologit outcome treatment controls
brant // Brant test (if installed: ssc install brant)
* If violated, use generalized ordered logit:
gologit2 outcome treatment controls, autofitFor DiD/Event Study:
* Event study with csdid
csdid outcome, ivar(id) time(year) gvar(first_treat) notyet
csdid_estat event
csdid_plot, title("Event Study")
graph export "$figures/event_study.pdf", replaceFor IV:
* First stage F-statistic
ivreg2 outcome (endogenous = instrument) controls, first robust
* Check F > 10 (or use effective F)
* Display first stage
estat firststage5. Visualize Key Results
Create figures for the main findings:
Coefficient plot:
coefplot m4, drop(_cons) xline(0) ///
title("Treatment Effect Estimate") ///
xtitle("Coefficient") ytitle("")
graph export "$figures/coefplot.pdf", replaceEvent study plot:
* After csdid
csdid_plot, ///
title("Dynamic Treatment Effects") ///
xtitle("Time Relative to Treatment") ///
ytitle("Coefficient")
graph export "$figures/event_study.pdf", replaceMarginal effects (for interactions):
* If model has interactions
margins, dydx(treatment) at(moderator=(0 1))
marginsplot, ///
title("Treatment Effect by Moderator") ///
xtitle("Moderator") ytitle("Marginal Effect")
graph export "$figures/margins.pdf", replaceOutput: Results Report
Create a results report (memos/phase3-results-report.md):
# Main Results Report
## Summary of Findings
**Main estimate**: [interpretation in words]
The preferred specification (Model X) shows that [treatment] is associated with
a [magnitude] [direction] in [outcome]. This effect is [statistically significant
at the X% level / not statistically significant].
## Results Table
[Reference Table 2 or include formatted output]
## Interpretation
### Magnitude
- Point estimate: [value]
- Units: [what this means]
- Context: [comparison to mean/SD/other benchmark]
### Precision
- Standard error: [value]
- 95% CI: [lower, upper]
- This is [precise/noisy] because [reason]
### Stability
- The estimate [is stable / changes] across specifications
- Adding controls [increases/decreases/doesn't change] the estimate
- This suggests [interpretation of stability pattern]
## Diagnostic Checks
- [Results of assumption tests]
- [Any concerns raised]
## Visualizations
- Figure X: [description]
- Figure Y: [description]
## Preliminary Assessment
- These results [support / do not support / partially support] the hypothesis
- Key caveat: [main limitation]
- Next step: robustness checks in Phase 4
## Questions for User
- [Any interpretive questions]
- [Should we proceed to robustness?]When You're Done
Return a summary to the orchestrator that includes: 1. The main estimate and its interpretation 2. Whether the effect is statistically significant 3. Whether results are stable across specifications 4. Any diagnostic concerns 5. Questions for the user
Do not proceed to Phase 4 until the user reviews the main results.
Phase 4: Robustness & Sensitivity
You are executing Phase 4 of a statistical analysis in Stata. Your goal is to stress-test the main findings through robustness checks and sensitivity analysis.
Why This Phase Matters
Main results are only as credible as their robustness. Reviewers will ask: "How do you know this isn't driven by [X]?" This phase pre-empts those questions and honestly assesses the fragility of the findings.
Technique Guides
Consult these guides in stata-statistical-techniques/ for robustness code patterns:
| Topic | Guide |
|---|---|
| DiD robustness, Event studies | 01_core_econometrics.md |
| Bootstrap, Wild cluster | 02_survey_resampling.md |
| Matching diagnostics | 01_core_econometrics.md Section 5 |
| Post-estimation tests | 07_postestimation_reporting.md |
Your Tasks
1. Alternative Specifications
Run the pre-specified alternatives from Phase 2:
Different control sets:
* Minimal controls
reghdfe outcome treatment, absorb(id year) cluster(cluster_var)
estimates store robust_minimal
* Extended controls
reghdfe outcome treatment extra1 extra2 extra3, absorb(id year) cluster(cluster_var)
estimates store robust_extended
* Different functional form
gen log_outcome = log(outcome)
reghdfe log_outcome treatment control1 control2, absorb(id year) cluster(cluster_var)
estimates store robust_logDifferent fixed effects:
* More demanding FE structure
reghdfe outcome treatment, absorb(id#year) cluster(cluster_var)
estimates store robust_fe1
* Region-by-year FE
reghdfe outcome treatment, absorb(region#year id) cluster(cluster_var)
estimates store robust_fe2Different standard errors:
* Compare clustering levels
reghdfe outcome treatment control1 control2, absorb(id year) cluster(id)
estimates store se_id
reghdfe outcome treatment control1 control2, absorb(id year) cluster(state)
estimates store se_state
reghdfe outcome treatment control1 control2, absorb(id year) cluster(id year)
estimates store se_twoway2. Placebo Tests
Pre-treatment effects (for DiD/Event Study):
* Should see no effect before treatment
preserve
keep if year < treatment_year
reghdfe outcome fake_treatment, absorb(id year) cluster(id)
estimates store placebo_pre
restoreFake treatment timing:
* Assign treatment X years earlier—should find no effect
gen fake_treated = treated_post & year >= (treatment_year - 3)
reghdfe outcome fake_treated, absorb(id year) cluster(id)
estimates store placebo_timingOutcome that shouldn't be affected:
* If treatment affects X, it shouldn't affect unrelated Y
reghdfe unrelated_outcome treatment control1 control2, absorb(id year) cluster(id)
estimates store placebo_outcome3. Wild Cluster Bootstrap
For designs with few clusters (<50):
* After main estimation
reghdfe outcome treatment control1 control2, absorb(id year) cluster(state)
* Wild cluster bootstrap
boottest treatment, cluster(state) reps(999) nograph
* Store p-value for reporting4. Missing Data Assessment
Before running sensitivity analyses, document and address missing data:
Document Missingness:
* Overall missingness rates
misstable summarize
misstable patterns
* Missingness by key variables
bysort treatment: misstable summarize outcome control1 control2Test for MCAR/MAR:
* Little's MCAR test (if installed: ssc install mcartest)
mcartest outcome control1 control2
* Visualize missingness patterns
misstable patterns, frequencyMultiple Imputation (if substantial missingness):
* Use adequate number of imputations (m ≥ 20, preferably ≥ 50)
mi set wide
mi register imputed outcome control1 control2
mi impute chained (regress) outcome control1 control2 = treatment, add(50) rseed(12345)
* Check imputation diagnostics
mi xeq: summarize outcome control1 control2
* Run analysis on imputed datasets and pool
mi estimate: reghdfe outcome treatment control1 control2, absorb(id year) cluster(cluster_var)
* Include auxiliary variables to strengthen MAR assumption
* These are variables that predict missingness or the outcomeCompare Missing Data Approaches:
* Store estimates for comparison
* Complete case
reghdfe outcome treatment control1 control2, absorb(id year) cluster(cluster_var)
estimates store complete_case
* Multiple imputation
mi estimate: reghdfe outcome treatment control1 control2, absorb(id year) cluster(cluster_var)
estimates store mi_model
* Create comparison table
esttab complete_case mi_model using "$tables/missing_data_sensitivity.rtf", replace ///
se star(* 0.10 ** 0.05 *** 0.01) ///
mtitles("Complete Case" "Multiple Imputation") ///
title("Sensitivity to Missing Data Treatment")Report in Methods Section:
[X]% of observations were missing on [variable]. We tested for patterns
of missingness and found [MCAR/MAR/evidence of MNAR]. Our primary analysis
uses [complete case / multiple imputation with m = X imputations].
Sensitivity analyses comparing complete case and multiple imputation show
[results are robust / estimates differ by X].5. Panel/Longitudinal Data Robustness (If Applicable)
Attrition Analysis:
* Document attrition rates by wave
tab wave, sum(n_obs)
* Test if attrition is related to treatment or outcomes
gen dropped_out = (next_wave_outcome == .)
logit dropped_out treatment baseline_outcome covariates, vce(robust)Inverse Probability Weighting for Selection:
* Estimate selection weights
logit observed treatment covariates
predict ps, pr
gen ipw = 1 / ps
* Apply weights in main analysis
reghdfe outcome treatment control1 control2 [pw=ipw], absorb(id year) cluster(cluster_var)
estimates store robust_ipwFixed vs Random Effects:
* Hausman test
xtreg outcome treatment covariates, fe
estimates store fe
xtreg outcome treatment covariates, re
estimates store re
hausman fe re // p < 0.05 suggests FE preferred
* Within-between decomposition (correlated random effects)
* Create between-unit and within-unit deviations
bysort id: egen treatment_mean = mean(treatment)
gen treatment_within = treatment - treatment_mean
xtreg outcome treatment_within treatment_mean covariates, re6. Sensitivity Analysis
Sensitivity to outliers:
* Winsorize extreme values
winsor2 outcome, cuts(1 99) suffix(_w)
reghdfe outcome_w treatment control1 control2, absorb(id year) cluster(cluster_var)
estimates store robust_winsor
* Drop extreme observations
summarize outcome, detail
drop if outcome < r(p1) | outcome > r(p99)
reghdfe outcome treatment control1 control2, absorb(id year) cluster(cluster_var)
estimates store robust_trimSensitivity to sample restrictions:
* Different time periods
reghdfe outcome treatment control1 control2 if year <= 2015, ///
absorb(id year) cluster(cluster_var)
estimates store robust_early
reghdfe outcome treatment control1 control2 if year > 2015, ///
absorb(id year) cluster(cluster_var)
estimates store robust_late
* Excluding specific units
reghdfe outcome treatment control1 control2 if !outlier_unit, ///
absorb(id year) cluster(cluster_var)
estimates store robust_exclude5. Subgroup Analysis
Run pre-specified heterogeneity analyses:
* By group (separate regressions)
reghdfe outcome treatment control1 control2 if subgroup == 1, ///
absorb(id year) cluster(cluster_var)
estimates store het_group1
reghdfe outcome treatment control1 control2 if subgroup == 0, ///
absorb(id year) cluster(cluster_var)
estimates store het_group2
* Interaction approach (preferred)
reghdfe outcome c.treatment##i.subgroup control1 control2, ///
absorb(id year) cluster(cluster_var)
estimates store het_interact
* Test difference
test 1.subgroup#c.treatment6. Method-Specific Diagnostics
For DiD with staggered treatment:
* Check for heterogeneous treatment effects
csdid outcome, ivar(id) time(year) gvar(first_treat) notyet
csdid_estat event
* Compare to traditional TWFE
reghdfe outcome treated, absorb(id year) cluster(id)
* Note any differencesFor IV:
* Weak instrument test
ivreg2 outcome (endogenous = instrument) controls, first robust
* Check F > 10
* Overidentification test (if multiple instruments)
ivreg2 outcome (endogenous = inst1 inst2) controls, robust
estat overidFor Matching:
* Balance check after matching
pstest control1 control2 control3, both graph
graph export "$figures/balance.pdf", replace7. Create Robustness Table
Compile all robustness checks:
esttab m4 robust_minimal robust_extended robust_fe1 robust_winsor robust_early robust_late ///
using "$tables/table3_robustness.rtf", replace ///
se star(* 0.10 ** 0.05 *** 0.01) ///
keep(treatment) ///
mtitles("Main" "Minimal" "Extended" "Alt FE" "Winsor" "Pre-2015" "Post-2015") ///
title("Robustness Checks") ///
note("All models include unit and year fixed effects. SE clustered at [level].")Output: Robustness Report
Create a robustness report (memos/phase4-robustness-report.md):
# Robustness Report
## Summary Assessment
The main findings are [robust / partially robust / not robust] to alternative specifications.
## Alternative Specifications
| Specification | Estimate | SE | Conclusion |
|---------------|----------|-----|------------|
| Main | X.XX | (X.XX) | - |
| Minimal controls | X.XX | (X.XX) | [stable/different] |
| Extended controls | X.XX | (X.XX) | [stable/different] |
| Alt FE | X.XX | (X.XX) | [stable/different] |
...
## Placebo Tests
| Test | Expected | Found | Pass? |
|------|----------|-------|-------|
| Pre-treatment | 0 | X.XX (p=X.XX) | [Yes/No] |
| Fake timing | 0 | X.XX (p=X.XX) | [Yes/No] |
| Unrelated outcome | 0 | X.XX (p=X.XX) | [Yes/No] |
## Wild Cluster Bootstrap
- Conventional p-value: [X.XX]
- Bootstrap p-value: [X.XX]
- Inference [changes / doesn't change]
## Sensitivity Analysis
### Outliers
- Results [are / are not] sensitive to extreme values
### Sample restrictions
- Results [hold / change] in different subsamples
## Subgroup Analysis
| Subgroup | Estimate | SE | Different from main? |
|----------|----------|-----|---------------------|
| Group 1 | X.XX | (X.XX) | [Yes/No] |
| Group 2 | X.XX | (X.XX) | [Yes/No] |
## Method-Specific Diagnostics
[Results of diagnostic tests]
## Overall Assessment
**Strengths:**
- [What checks the results passed]
**Concerns:**
- [Any issues found]
**Conclusion:**
The main findings [can / cannot] be considered robust because [reasoning].
## Questions for User
- [Any interpretive questions about robustness]When You're Done
Return a summary to the orchestrator that includes: 1. Overall robustness assessment 2. Which checks passed/failed 3. Wild bootstrap results (if applicable) 4. Any concerns about the findings 5. Questions for the user
Do not proceed to Phase 5 until the user reviews the robustness assessment.
Phase 5: Output & Interpretation
You are executing Phase 5 of a statistical analysis in Stata. Your goal is to produce publication-ready outputs and synthesize the analysis into a coherent narrative.
Why This Phase Matters
Analysis isn't complete until it's communicated. This phase transforms results into tables, figures, and text that can appear in a journal article. Good output is accurate, clear, and tells a story.
Technique Guides
Consult these guides in stata-statistical-techniques/ for output code patterns:
| Topic | Guide |
|---|---|
| Tables (esttab, estout) | 04_visualization.md |
| Figures (coefplot, graphs) | 04_visualization.md |
| Table 1, Descriptives | 07_postestimation_reporting.md |
| Project structure, Master do-files | 05_best_practices.md |
| Complete project template | 99_default_journal_pipeline.md |
Your Tasks
1. Finalize Tables
Table 1: Descriptive Statistics
* Summary statistics
estpost summarize outcome treatment control1 control2
esttab using "$tables/table1_descriptives.rtf", replace ///
cells("count(fmt(0)) mean(fmt(2)) sd(fmt(2)) min(fmt(2)) max(fmt(2))") ///
title("Summary Statistics") ///
note("Sample: [description]. Source: [data source].")
* Balance table (if applicable)
estpost ttest outcome control1 control2, by(treatment)
esttab using "$tables/table1_balance.rtf", replace ///
cells("mu_1(fmt(2)) mu_2(fmt(2)) b(fmt(2) star)") ///
collabels("Control" "Treated" "Difference") ///
star(* 0.10 ** 0.05 *** 0.01) ///
title("Balance Across Treatment Groups")Table 2: Main Results
esttab m1 m2 m3 m4 using "$tables/table2_main.rtf", replace ///
se star(* 0.10 ** 0.05 *** 0.01) ///
keep(treatment) ///
coeflabels(treatment "Treatment Effect") ///
stats(N r2_a, labels("Observations" "Adj. R-squared") fmt(0 3)) ///
mtitles("(1)" "(2)" "(3)" "(4)") ///
title("Effect of [Treatment] on [Outcome]") ///
addnotes("Standard errors clustered at [level] in parentheses." ///
"All models include [FE description]." ///
"* p<0.1, ** p<0.05, *** p<0.01")
* LaTeX version
esttab m1 m2 m3 m4 using "$tables/table2_main.tex", replace ///
se star(* 0.10 ** 0.05 *** 0.01) booktabs ///
keep(treatment) ///
stats(N r2_a, labels("Observations" "Adj. R-squared") fmt(0 3))Table 3: Robustness
esttab main robust1 robust2 robust3 robust4 using "$tables/table3_robustness.rtf", replace ///
se star(* 0.10 ** 0.05 *** 0.01) ///
keep(treatment) ///
mtitles("Main" "Alt 1" "Alt 2" "Alt 3" "Alt 4") ///
title("Robustness Checks") ///
note("See notes to Table 2.")2. Create Publication Figures
Figure 1: Trends (for DiD)
preserve
collapse (mean) mean_outcome=outcome (sd) sd_outcome=outcome (count) n=outcome, ///
by(year treatment_group)
gen se = sd_outcome / sqrt(n)
gen ci_low = mean_outcome - 1.96*se
gen ci_high = mean_outcome + 1.96*se
twoway (rarea ci_low ci_high year if treatment_group==0, color(blue%20)) ///
(rarea ci_low ci_high year if treatment_group==1, color(red%20)) ///
(line mean_outcome year if treatment_group==0, lcolor(blue) lwidth(medium)) ///
(line mean_outcome year if treatment_group==1, lcolor(red) lwidth(medium)) ///
(scatter mean_outcome year if treatment_group==0, mcolor(blue)) ///
(scatter mean_outcome year if treatment_group==1, mcolor(red)), ///
xline(`treatment_year', lpattern(dash) lcolor(gray)) ///
legend(order(3 "Control" 4 "Treated") rows(1) position(6)) ///
xtitle("Year") ytitle("Outcome") ///
title("") ///
graphregion(color(white)) bgcolor(white)
graph export "$figures/figure1_trends.pdf", replace
restoreFigure 2: Event Study
* After csdid estimation
csdid_plot, ///
style(rcap) ///
title("") ///
xtitle("Time Relative to Treatment") ///
ytitle("Coefficient Estimate") ///
graphregion(color(white)) bgcolor(white)
graph export "$figures/figure2_eventstudy.pdf", replaceFigure 3: Coefficient Plot
coefplot m4, ///
keep(treatment) ///
xline(0, lpattern(dash) lcolor(gray)) ///
title("") ///
xtitle("Coefficient Estimate") ///
graphregion(color(white)) bgcolor(white)
graph export "$figures/figure3_coefplot.pdf", replace3. Write Results Narrative
Draft the key paragraphs for the results section:
Main effect paragraph:
Table 2 presents estimates of the effect of [treatment] on [outcome].
Column (1) shows the baseline relationship without controls.
Column (4), our preferred specification, includes [unit] and [time] fixed effects
and clusters standard errors at the [level] level. We find that [treatment]
[increases/decreases] [outcome] by [X] [units], significant at the [Y]% level
(95% CI: [lower, upper]). This represents a [Z]% change relative to the
pre-treatment mean of [mean].
Robustness paragraph:
Table 3 demonstrates that this finding is robust to alternative specifications.
The point estimate remains [stable/similar] when we [change 1], [change 2], and
[change 3]. The effect is [somewhat/not] sensitive to [what]. The wild cluster
bootstrap p-value of [X] confirms that inference is [robust/sensitive] to
the number of clusters.
Heterogeneity paragraph (if applicable):
We examine heterogeneity in treatment effects across [subgroups].
Table X shows that the effect is [larger/smaller] for [group 1]
([estimate]) compared to [group 2] ([estimate]). This difference is
[statistically significant / not statistically significant] (p = [value]).
4. Survey Data Methods Section (If Applicable)
For survey-based analyses, address the five survey methodology deliverables:
1. Sampling Frame Description:
Data come from the [SURVEY NAME], a [DESIGN TYPE] of [POPULATION].
The sampling frame is [DESCRIPTION]. The target population is [WHO].
[Exclusions]: We exclude [categories] because [reason].2. Response Rate and Nonresponse:
The response rate was [X]% (calculated as [METHOD: AAPOR RR1/RR3/etc.]).
We compared respondents to [population benchmark / nonrespondents on X variables]
and found [no significant differences / differences on X that we address through Y].3. Weighting Justification:
We apply [WEIGHT TYPE: post-stratification / raking / none] weights to adjust for
[FACTORS]. Weights are provided by [SOURCE] and calibrated to [BENCHMARKS].
[Alternative: We do not apply weights because {justification}.]4. Survey Design Acknowledgment:
* Define survey design
svyset [pw=weight], strata(stratum) psu(psu)
* All analyses use survey-adjusted estimates
svy: mean outcome
svy: regress outcome treatment control1 control25. Population Inference Boundaries:
Our results generalize to [POPULATION] during [TIME PERIOD]. We cannot
speak to [EXCLUDED GROUPS / OTHER TIME PERIODS] because [REASON].5. Document Limitations
Identify and articulate limitations honestly:
## Limitations
1. **[Identification limitation]**: Our identification strategy relies on
[assumption]. While we provide evidence supporting this assumption through
[tests], we cannot definitively rule out [threat].
2. **[External validity]**: Our sample consists of [description]. Results may
not generalize to [other contexts] because [reason].
3. **[Measurement]**: [Variable] is measured using [method], which may
[limitation]. We address this by [mitigation] but acknowledge [remaining concern].
4. **[Data limitation]**: We lack data on [variable], which could [potential issue].
Our robustness checks in Table X suggest this is [unlikely to/may] affect our
conclusions.5. Create Replication Package
Prepare materials for reproducibility:
* Master do-file header
* ============================================================
* Replication Code for "[Paper Title]"
* Authors: [Names]
* Date: [Date]
*
* This script reproduces all tables and figures in the paper.
* Runtime: approximately [X] minutes
*
* Requirements:
* Stata version: 15+
* Packages: reghdfe, estout, coefplot, csdid
* ============================================================
version 15
clear all
set more off
* Install required packages (uncomment if needed)
* ssc install reghdfe
* ssc install estout
* ssc install coefplot
* ssc install csdid
* Set root path (CHANGE THIS)
global root "[path to replication folder]"
* Derived paths
global code "$root/code"
global data "$root/data"
global raw "$data/raw"
global clean "$data/clean"
global tables "$root/output/tables"
global figures "$root/output/figures"
global logs "$root/logs"
* Start log
log using "$logs/replication_log.txt", text replace
* Run analysis
do "$code/01_clean_data.do"
do "$code/02_descriptives.do"
do "$code/03_main_analysis.do"
do "$code/04_robustness.do"
do "$code/05_figures.do"
* Report completion
display "Replication complete: " c(current_date) " " c(current_time)
display "Stata version: " c(stata_version)
log closeOutput: Final Report
Create the final synthesis (memos/phase5-final-report.md):
# Analysis Summary
## Key Finding
[One sentence summary of the main result]
## Main Result
- **Effect size**: [estimate with CI]
- **Significance**: [p-value or significance level]
- **Interpretation**: [what this means substantively]
## Robustness Assessment
- The finding [is/is not] robust to [list of checks]
- Main concerns: [if any]
## Output Files Created
### Tables
- `table1_descriptives.rtf`: Summary statistics
- `table2_main.rtf`: Main results
- `table3_robustness.rtf`: Robustness checks
### Figures
- `figure1_trends.pdf`: Pre/post trends
- `figure2_eventstudy.pdf`: Event study
- `figure3_coefplot.pdf`: Coefficient plot
### Replication Materials
- `00_master.do`: Master script
- `code/`: All analysis do-files
- `data/clean/`: Analysis datasets
- `logs/`: Stata log files
## Results Narrative
[Draft paragraphs for the paper]
## Limitations
[Honest assessment of limitations]
## Conclusion
[What can and cannot be concluded from this analysis]7. Pre-Submission Checklist
Before finalizing, verify the analysis meets publication standards:
Minimum Standard (Required):
- [ ] All variables clearly defined with units and coding
- [ ] Sample size and any exclusions documented
- [ ] Main coefficient table includes SEs and significance levels
- [ ] Standard error type specified (robust, clustered at X level, etc.)
- [ ] At least one robustness check reported
- [ ] Limitations section acknowledges main threats to validity
Strong Standard (Competitive for top journals):
- [ ] Descriptive statistics table with means, SDs, and sample sizes
- [ ] Multiple robustness specifications in appendix
- [ ] Effect sizes interpreted substantively (not just "significant")
- [ ] For nonlinear models: AMEs or predicted probabilities reported
- [ ] Wild cluster bootstrap for few-cluster designs
- [ ] Missing data approach documented and defended
- [ ] Visualization of key results (event study, coefficient plot, etc.)
- [ ] Replication code and data availability statement
Exemplary Standard (Model for the field):
- [ ] Pre-registration referenced (if applicable)
- [ ] Multiple identification strategies compared
- [ ] Heterogeneity analysis with theoretical motivation
- [ ] Mechanism analysis or mediation tests
- [ ] Power analysis or minimum detectable effects
- [ ] Bound analysis for worst-case scenarios
- [ ] Complete replication package with README
Language Checklist:
- [ ] Causal language only used with appropriate identification strategy
- [ ] Effect sizes interpreted relative to meaningful benchmarks
- [ ] Confidence intervals reported, not just p-values
- [ ] Scope conditions clearly stated
- [ ] "Significant" refers to statistical significance (or avoid the term)
When You're Done
Return a summary to the orchestrator that includes: 1. List of all tables and figures created 2. The main finding in one sentence 3. Key limitations 4. Any remaining questions or concerns 5. Confirmation that replication materials are ready 6. Checklist tier achieved (minimum/strong/exemplary)
The analysis is now complete. All materials should be ready for paper writing.
Data Preparation in Stata
Making "analysis-ready data" a reproducible, auditable stage. All code tested on Stata 15+.
---
0. Setup and Conventions
Minimal Header Template
* ===========================================================================
* Project: [Name]
* Purpose: [Brief description]
* Input: [raw data files]
* Output: [clean data files]
* ===========================================================================
clear all
set more off
version 15
set seed 12345
* Start log
log using "logs/01_data_prep.log", replaceNaming Conventions
- Variables:
snake_case(e.g.,first_treatment_year) - Files: descriptive, numbered (e.g.,
01_import.do,02_clean.do) - Always label variables after creating them
---
1. Import Patterns
Import CSV
* Basic import
import delimited "data/raw/mydata.csv", clear varnames(1)
* Force all columns as strings initially (for cleaning)
import delimited "data/raw/mydata.csv", clear varnames(1) stringcols(_all)
* Quick checks after import
describe
compress
codebook, compactImport Excel
* Basic import with first row as variable names
import excel "data/raw/mydata.xlsx", sheet("Sheet1") firstrow clear
* Import specific cell range
import excel "data/raw/mydata.xlsx", cellrange(A2:F100) firstrow clearReading Multiple Files (Loop)
* Append multiple CSV files from a folder
clear
local files: dir "data/raw/" files "*.csv"
local first = 1
foreach f of local files {
if `first' == 1 {
import delimited "data/raw/`f'", clear varnames(1)
local first = 0
}
else {
preserve
import delimited "data/raw/`f'", clear varnames(1)
tempfile temp
save `temp'
restore
append using `temp'
}
}Never Edit Raw Data
* Always save a clean .dta immediately after import
import delimited "data/raw/mydata.csv", clear varnames(1)
save "data/staging/mydata_imported.dta", replace---
2. Merge, Append, and Reshape
Every Merge Gets an Assertion
* 1:1 merge
use "data/master.dta", clear
merge 1:1 id using "data/using.dta"
* Required checks
tab _merge
count if _merge == 1 // master only
count if _merge == 2 // using only
count if _merge == 3 // matched
* Handle unmatched - be explicit about what you're dropping
assert _merge != 2 // or: drop if _merge == 2 with comment explaining why
drop _mergeMerge Patterns
* Many-to-one (e.g., individual-level to state-level)
merge m:1 state using "data/state_controls.dta"
* One-to-many (less common; be careful)
merge 1:m household_id using "data/household_members.dta"Key Verification Before Merge
* Check that merge keys are unique where expected
isid id // fails if id is not unique
duplicates report id // shows duplicate structure
duplicates tag id, gen(dup)
tab dup
drop dupAppend Pattern
* Append datasets
use "data/wave1.dta", clear
append using "data/wave2.dta"
* Track source
gen wave = 1
replace wave = 2 if _n > [original N]Reshape Wide to Long
* Example: income2018 income2019 income2020 -> income with year variable
clear
set obs 20
gen id = _n
gen income2018 = rnormal(50000, 10000)
gen income2019 = income2018 * 1.03 + rnormal(0, 1000)
gen income2020 = income2019 * 1.02 + rnormal(0, 1000)
reshape long income, i(id) j(year)Reshape Long to Wide
reshape wide income, i(id) j(year)---
3. Missing Data Audit
Missingness Summary
* Overall missing count
misstable summarize
* Missing by variable with patterns
misstable patternsMissing by Group
* Count non-missing by treatment group
tabstat x1 x2, by(treat) stat(n) nototal
* Count missing manually
count if missing(x1) & treat == 0
count if missing(x1) & treat == 1Rules of Thumb
- Never silently drop observations - always document exclusions
- Don't impute without justification - report complete-case as baseline
- Check missingness by key subgroups - differential attrition is a threat
Create Analysis Sample Flag
* Complete case indicator
gen sample_main = !missing(y, x1, x2, x3)
tab sample_main
* Or define incrementally with documentation
gen sample_main = 1
replace sample_main = 0 if missing(wage)
replace sample_main = 0 if missing(union)
replace sample_main = 0 if age < 25 | age > 55---
4. Recodes, Transforms, and Outliers
Standardize Special Missings
* Stata extended missing values: .a, .b, ... .z
replace income = .r if income == -99 // refused
replace income = .d if income == -88 // don't knowCommon Transforms
* Log transform
gen ln_income = ln(income)
* Handle zeros: ln(x + 1) or inverse hyperbolic sine
gen ln_income_p1 = ln(income + 1)
gen ihs_income = asinh(income)
* Standardization (z-scores)
egen z_income = std(income)
summarize z_income // mean = 0, sd = 1Create Categorical Variables with Labels
* Create categories
gen price_cat = 1 if price < 5000
replace price_cat = 2 if price >= 5000 & price < 10000
replace price_cat = 3 if price >= 10000 & !missing(price)
* Add labels
label define price_lbl 1 "Low" 2 "Medium" 3 "High"
label values price_cat price_lbl
tab price_catWinsorization (Optional)
* Winsorize at 1st and 99th percentiles
egen p1 = pctile(income), p(1)
egen p99 = pctile(income), p(99)
gen income_wins = income
replace income_wins = p1 if income < p1
replace income_wins = p99 if income > p99 & !missing(income)
drop p1 p99---
5. Panel/Time Setup and Sanity Checks
Declare Panel Structure
* xtset for panel data
xtset id time
xtdescribe
* tsset for time series (single unit)
tsset timeCheck for Gaps
* After xtset, check balance
xtdescribe
* Manual gap check
by id: gen gap = time - time[_n-1] if _n > 1
tab gap // should be all 1s if no gapsVerify Panel Structure
* Check unit counts and time coverage
tab id
tab time
distinct id
distinct timeTreatment Timing Construction
* Create first treatment year variable
gen treat_year = year if treatment == 1
bysort id: egen first_treat = min(treat_year)
drop treat_year
* Create relative time to treatment
gen rel_time = year - first_treat---
6. Sample Construction Documentation
Document Every Restriction
sysuse nlsw88, clear
* Track sample flow
display "Initial N: " _N
drop if missing(wage)
display "After dropping missing wage: " _N
drop if missing(union)
display "After dropping missing union: " _N
keep if age >= 25 & age <= 55
display "After age restriction (25-55): " _N
gen sample_main = 1
display "Final analysis sample: " _NSave Sample Flow to File
* Create sample flow log
file open flow using "$tables/sample_flow.txt", write replace
file write flow "Sample Construction" _n
file write flow "===================" _n
file write flow "Initial sample: 2,246" _n
file write flow "After dropping missing wage: 2,246" _n
file write flow "After dropping missing union: 1,878" _n
file write flow "Final analysis sample: 1,878" _n
file close flow---
7. Output Artifacts
Standard Save Pattern
* Save clean analysis dataset
compress
label data "Analysis sample, created [date]"
save "$clean/analysis_sample.dta", replaceExport Codebook
* Save variable documentation
codebook, compact
log using "$docs/codebook.log", replace
codebook
log close---
Quick Reference
Import Commands
| Task | Command |
|---|---|
| CSV | import delimited "file.csv", clear varnames(1) |
| Excel | import excel "file.xlsx", firstrow clear |
| Stata | use "file.dta", clear |
Merge Commands
| Type | Command |
|---|---|
| 1:1 | merge 1:1 id using "file.dta" |
| m:1 | merge m:1 group using "file.dta" |
| 1:m | merge 1:m id using "file.dta" |
Key Checks
| Task | Command |
|---|---|
| Unique ID | isid id |
| Duplicates | duplicates report id |
| Missing | misstable summarize |
| Panel setup | xtset id time then xtdescribe |
Stata Statistical Techniques - Index
Quick lookup for statistical methods in Stata. All code tested on Stata 15.1.
---
Core Workflow
For most journal-style analyses, follow this sequence:
1. Data Prep → 00_data_prep.md Import, merge, clean, construct variables, save analysis sample
2. Descriptives → 07_postestimation_reporting.md Table 1 (overall + by group), Figure 1 (trends or distributions)
3. Modeling → 06_modeling_basics.md OLS, logit/probit, margins, interactions
4. Causal Methods (if applicable) → 01_core_econometrics.md TWFE, DiD, IV, matching, RD
5. Output → 04_visualization.md, 07_postestimation_reporting.md Tables to RTF/TeX, figures to PNG/PDF
6. Pipeline Template → 99_default_journal_pipeline.md Copy this structure for new projects
---
File Guide
| File | Topics |
|---|---|
00_data_prep.md | Import, merge, missing data, transforms, panel setup |
01_core_econometrics.md | TWFE, DiD, Event Studies, IV, Matching, Mediation, Standard Errors |
02_survey_resampling.md | Survey Weights, Bootstrap, Randomization Inference, Oaxaca |
03_synthetic_control.md | synth package for comparative case studies |
04_visualization.md | esttab tables, coefplot, graphs, summary statistics |
05_best_practices.md | Master do-files, path management, code organization |
06_modeling_basics.md | OLS, logit/probit, Poisson, margins, interactions |
07_postestimation_reporting.md | Estimates workflow, predicted values, diagnostics, Table 1 |
99_default_journal_pipeline.md | Complete project template, file naming, submission checklist |
---
Quick Lookup by Method
Panel & Fixed Effects
- TWFE (reghdfe) →
01_core_econometrics.mdSection 1
Difference-in-Differences
- Traditional DiD →
01_core_econometrics.mdSection 2.1 - Callaway-Sant'Anna (csdid) →
01_core_econometrics.mdSection 2.2 - Event Studies →
01_core_econometrics.mdSection 3
Instrumental Variables
- Basic 2SLS (ivreg2) →
01_core_econometrics.mdSection 4 - First-stage diagnostics →
01_core_econometrics.mdSection 4.2 - Overidentification tests →
01_core_econometrics.mdSection 4.3
Matching
- Propensity Score (psmatch2) →
01_core_econometrics.mdSection 5.1 - Coarsened Exact (cem) →
01_core_econometrics.mdSection 5.3 - Balance testing (pstest) →
01_core_econometrics.mdSection 5.2
Standard Errors & Inference
- Clustered SEs →
01_core_econometrics.mdSection 6.1 - Wild Cluster Bootstrap →
01_core_econometrics.mdSection 6.2 - Randomization Inference →
02_survey_resampling.mdSection 4
Survey Methods
- Survey design (svyset) →
02_survey_resampling.mdSection 1 - Weighted estimation (svy:) →
02_survey_resampling.mdSection 1 - Subpopulation analysis →
02_survey_resampling.mdSection 1
Decomposition
- Oaxaca-Blinder →
02_survey_resampling.mdSection 5
Synthetic Control
- synth package →
03_synthetic_control.md
Output & Visualization
- Regression tables (esttab) →
04_visualization.mdSection 1 - Coefficient plots (coefplot) →
04_visualization.mdSection 2 - Summary statistics →
04_visualization.mdSection 3
Data Preparation
- Import CSV/Excel →
00_data_prep.mdSection 1 - Merge patterns →
00_data_prep.mdSection 2 - Missing data audit →
00_data_prep.mdSection 3 - Reshape →
00_data_prep.mdSection 2 - Panel setup (xtset) →
00_data_prep.mdSection 5
Basic Modeling
- OLS with robust/clustered SEs →
06_modeling_basics.mdSection 1 - Interactions and margins →
06_modeling_basics.mdSection 2 - Logit/Probit →
06_modeling_basics.mdSection 3 - Marginal effects (AME) →
06_modeling_basics.mdSection 3 - Poisson/Negative Binomial →
06_modeling_basics.mdSection 4 - Ordinal logit →
06_modeling_basics.mdSection 5 - VIF and diagnostics →
06_modeling_basics.mdSection 7
Post-Estimation
- Estimates store/restore →
07_postestimation_reporting.mdSection 1 - Nested tables →
07_postestimation_reporting.mdSection 2 - Predicted values →
07_postestimation_reporting.mdSection 3 - Table 1 (descriptives) →
07_postestimation_reporting.mdSection 5 - Balance tables →
07_postestimation_reporting.mdSection 6
Reporting Checklists
- TWFE checklist →
01_core_econometrics.mdReporting Checklists - DiD checklist →
01_core_econometrics.mdReporting Checklists - IV checklist →
01_core_econometrics.mdReporting Checklists - Matching checklist →
01_core_econometrics.mdReporting Checklists
---
Package Quick Reference
| Task | Package | Command |
|---|---|---|
| High-dim FE | reghdfe | reghdfe y x, absorb(id year) cluster(id) |
| Modern DiD | csdid | csdid y, ivar(id) time(year) gvar(gvar) notyet |
| DiD event study | csdid_estat | csdid_estat event |
| IV estimation | ivreg2 | ivreg2 y (endog = iv), first robust |
| PSM | psmatch2 | psmatch2 treat x1 x2, outcome(y) |
| Balance test | pstest | pstest x1 x2, both |
| CEM | cem | cem x1 (bins) x2 (#5), treatment(treat) |
| Wild bootstrap | boottest | boottest x, cluster(c) reps(999) nograph |
| Randomization | ritest | ritest treat _b[treat], reps(500): |
| Oaxaca | oaxaca | oaxaca y x1 x2, by(group) |
| Synth control | synth | synth y x1 y(1985), trunit(1) trperiod(1990) |
| Tables | estout | esttab m1 m2, se star(* .10 ** .05 *** .01) |
| Coef plots | coefplot | coefplot, drop(_cons) xline(0) |
| Survey | built-in | svyset psu [pw=wt], strata(strat) |
---
Built-in Datasets for Examples
| Dataset | Command | Variables |
|---|---|---|
| auto | sysuse auto | price, mpg, weight, foreign |
| nlsw88 | sysuse nlsw88 | wage, union, age, grade, tenure |
| nhanes2f | webuse nhanes2f | height, weight, age, sex, finalwgt |
---
Version Notes
- Stata 15+: All methods except rdrobust
- Stata 16+: rdrobust (RD estimation)
Core Econometrics in Stata
Panel methods, causal inference, and standard errors. All code tested on Stata 15+.
---
1. Two-Way Fixed Effects (TWFE)
When to Use
- Panel data with unit and time dimensions
- Unobserved unit and time confounders
- Consistent treatment timing (or verified no negative weights)
Basic TWFE with reghdfe
* Declare panel
xtset id period
* TWFE with unit and time fixed effects, clustered SEs
reghdfe y x1 treat, absorb(id period) cluster(id)Two-Way Clustering
* Cluster by both unit and time
reghdfe y x1 treat, absorb(id period) cluster(id period)Store and Compare Models
* Run models
quietly reghdfe y x1 treat, absorb(id period) cluster(id)
estimates store m1_oneway
quietly reghdfe y x1 treat, absorb(id period) cluster(id period)
estimates store m2_twoway
* Comparison table
esttab m1_oneway m2_twoway, se mtitle("One-way" "Two-way") ///
star(* 0.10 ** 0.05 *** 0.01)---
2. Difference-in-Differences (DiD)
2.1 Traditional DiD
* Create interaction term
gen treat_post = treated_group * post_period
* DiD regression with FE
reghdfe y treat_post, absorb(id period) cluster(id)
* Or explicit interaction
reg y i.treated_group##i.post_period x1, cluster(id)2.2 Callaway-Sant'Anna (Staggered Treatment)
For heterogeneous treatment effects with staggered timing:
* Data setup:
* - gvar: first treatment period (0 for never-treated)
* - id: panel unit identifier
* - year: time period
* Run csdid
csdid y, ivar(id) time(year) gvar(gvar) notyet
* Event study aggregation
csdid_estat event
* Simple ATT
csdid_estat simpleKey options:
notyet: Use not-yet-treated as control (recommended)never: Use never-treated as control only
2.3 Post-Estimation for csdid
* After running csdid:
* Event study (dynamic effects)
csdid_estat event
* Group-time ATTs
csdid_estat group
* Calendar time ATTs
csdid_estat calendar
* Simple overall ATT
csdid_estat simple---
3. Event Studies
Manual Event Study
* Create event time relative to treatment
gen event_time = year - first_treat
replace event_time = -99 if missing(first_treat) // Never treated
* Bin endpoints
replace event_time = -5 if event_time < -5 & event_time != -99
replace event_time = 5 if event_time > 5 & event_time != -99
* Create dummies (omit t=-1 as reference)
tab event_time, gen(et_)
* Estimate (drop reference period)
reghdfe y et_1 et_2 et_3 et_4 et_6 et_7 et_8 et_9 et_10 et_11, ///
absorb(id year) cluster(id)Event Study from csdid
* Run csdid first
csdid y, ivar(id) time(year) gvar(gvar) notyet
* Get event study estimates
csdid_estat event---
4. Instrumental Variables (IV)
4.1 Basic 2SLS
* Built-in ivregress
ivregress 2sls y (x_endog = z), robust
estat firststage
* ivreg2 with more diagnostics
ivreg2 y (x_endog = z), first robust4.2 IV Diagnostics
ivreg2 automatically reports:
- First-stage F-statistic: Should be > 10 (Stock-Yogo rule)
- Kleibergen-Paap rk F: Robust weak instrument test
- Anderson-Rubin CI: Weak-instrument-robust confidence interval
* Detailed first-stage output
ivreg2 y (x_endog = z), first robust
* Key output to check:
* - F test of excluded instruments: F > 10
* - Stock-Yogo critical values for comparison
* - Kleibergen-Paap rk Wald F statistic4.3 Multiple Instruments (Overidentification)
* Multiple instruments
ivreg2 y (x_endog = z1 z2), robust
* Hansen J statistic (overidentification test) reported automatically
* H0: All instruments are valid
* High p-value = cannot reject validity4.4 IV with Fixed Effects
* Using ivreghdfe (install: ssc install ivreghdfe)
ivreghdfe y (x_endog = z), absorb(id year) cluster(id)---
5. Matching Methods
5.1 Propensity Score Matching
* psmatch2: estimate PS and match
psmatch2 treat x1 x2 i.category, outcome(y) neighbor(1) common
* Check balance
pstest x1 x2, both
* The ATT is displayed in the output tableKey options:
neighbor(k): k nearest neighborscaliper(c): Maximum PS distancecommon: Restrict to common support
5.2 Balance Assessment
* After psmatch2
pstest x1 x2, both
* Output shows:
* - Mean bias before/after matching
* - % reduction in bias
* - t-tests for balance5.3 Coarsened Exact Matching (CEM)
* CEM with specified bins
cem age (20 30 40 50 60) grade (#5), treatment(treat)
* Estimate with CEM weights
reg y treat x1 x2 [iweight=cem_weights], robust---
6. Standard Errors and Inference
6.1 Clustered Standard Errors
* One-way clustering
reghdfe y x treat, absorb(id period) cluster(id)
* Two-way clustering
reghdfe y x treat, absorb(id period) cluster(id period)6.2 Wild Cluster Bootstrap (Few Clusters)
When you have fewer than ~40 clusters:
* Run regression with clustering
reg y treat x, cluster(state)
* Wild cluster bootstrap
boottest treat, cluster(state) reps(999) seed(12345) nograph
* Output:
* - Bootstrap t-statistic
* - Bootstrap p-value
* - 95% confidence interval6.3 Standard Bootstrap
* Bootstrap standard errors
bootstrap _b, reps(500) seed(12345): reg y x1 x2 treat
* Bootstrap specific statistics
bootstrap diff = (_b[treat]), reps(500) seed(12345): reg y x1 treat6.4 Randomization Inference
* Permutation test with stratification
ritest treat _b[treat], reps(500) seed(12345) strata(block): ///
reg y treat, robust
* Output shows:
* - Observed coefficient
* - p-value from permutation distribution---
7. Regression Discontinuity (RD)
Note: The rdrobust package requires Stata 16+. For Stata 15, use manual polynomial approaches.
Manual RD (Stata 15 compatible)
* Create centered running variable
gen x_centered = running_var - cutoff
* Treatment indicator
gen treat = (running_var >= cutoff)
* Local linear regression (narrow bandwidth)
reg y treat x_centered c.x_centered#i.treat if abs(x_centered) < bandwidth
* The coefficient on treat is the RD estimaterdrobust (Stata 16+)
* Basic RD estimation
rdrobust y running_var, c(0)
* With options
rdrobust y running_var, c(0) kernel(triangular) bwselect(mserd)
* Manipulation test
rddensity running_var, c(0)
* RD plot
rdplot y running_var, c(0)---
8. Causal Mediation
* Mediation analysis requires:
* - Treatment variable (treat)
* - Mediator variable (m)
* - Outcome variable (y)
* Using medeff (install: ssc install medeff)
* Step 1: Mediator model
reg m treat x1
* Step 2: Outcome model
reg y treat m x1
* Step 3: Mediation effects
medeff (reg m treat x1) (reg y treat m x1), ///
treat(treat) mediate(m) sims(1000)
* Output:
* - ACME: Average Causal Mediation Effect (indirect)
* - ADE: Average Direct Effect
* - Total Effect: ACME + ADE
* - Proportion Mediated: ACME / Total---
Quick Reference
Package Installation
* Core packages
ssc install reghdfe, replace
ssc install ftools, replace
ssc install estout, replace
ssc install coefplot, replace
* DiD methods
ssc install csdid, replace
ssc install drdid, replace
* IV
ssc install ivreg2, replace
ssc install ranktest, replace
* Matching
ssc install psmatch2, replace
ssc install cem, replace
* Inference
ssc install boottest, replace
ssc install ritest, replace
* RD (Stata 16+ only)
ssc install rdrobust, replace
ssc install rddensity, replaceCommand Quick Reference
| Task | Command |
|---|---|
| TWFE | reghdfe y x, absorb(id t) cluster(id) |
| Modern DiD | csdid y, ivar(id) time(t) gvar(g) |
| Event study | csdid_estat event |
| IV | ivreg2 y (endog = iv), first robust |
| PSM | psmatch2 treat x, outcome(y) |
| CEM | cem x1 x2, treatment(treat) |
| Wild bootstrap | boottest x, cluster(c) nograph |
| Randomization | ritest treat _b[treat], reps(500): |
Diagnostic Checks
1. TWFE: Check for negative weights with staggered timing 2. DiD: Test parallel trends with event study pre-trends 3. IV: First-stage F > 10, check overidentification 4. Matching: Balance statistics with pstest 5. Clustering: Use wild bootstrap with < 40 clusters
---
Reporting Checklists
TWFE Checklist
Required in methods section:
- [ ] Define panel structure (unit ID, time variable)
- [ ] Specify fixed effects included (unit FE, time FE, or both)
- [ ] Justify clustering level (theory-based: state, firm, etc.)
Report in results:
- [ ] N units, N time periods, N observations
- [ ] Fixed effects included (state FE, year FE, etc.)
- [ ] Key coefficient, SE, and CI
- [ ] Clustering level in table notes
Sensitivity checks:
- [ ] Alternative clustering (one-way vs two-way if plausible)
- [ ] Results stable across specifications
---
DiD Checklist (Traditional & Staggered)
Required in methods section:
- [ ] Treatment definition and timing
- [ ] Control group definition (never-treated vs not-yet-treated)
- [ ] Parallel trends assumption justification
Report in results:
- [ ] Baseline DiD estimate + SE
- [ ] Event study plot with pre-trend coefficients
- [ ] Discuss pre-trends (are they flat and near zero?)
Robustness checks:
- [ ] Alternative control group (for
csdid: togglenotyetvsnever) - [ ] Alternative event window bins (e.g., 2-year vs 1-year)
- [ ] Wild cluster bootstrap if < 40 clusters (use
boottest)
---
IV Checklist
Required in methods section:
- [ ] Instrument relevance story (why does Z predict X?)
- [ ] Exclusion restriction argument (why does Z only affect Y through X?)
Report in results:
- [ ] First-stage F-statistic (or Kleibergen-Paap rk F from
ivreg2) - [ ] Stock-Yogo critical values for weak instrument comparison
- [ ] Overidentification test (Hansen J) if multiple instruments
- [ ] 2SLS coefficient + SE
Robustness checks:
- [ ] Reduced form regression (Y on Z directly)
- [ ] Alternative instrument sets or control variables
- [ ] Anderson-Rubin weak-instrument-robust CI
---
Matching Checklist
Required in methods section:
- [ ] Covariate set justification (what variables predict treatment?)
- [ ] Common support/overlap rule
- [ ] Matching method choice (PSM, CEM, etc.)
Report in results:
- [ ] Balance table: before vs after matching (
pstest) - [ ] ATT estimate + SE
- [ ] Number matched, number dropped for common support
Robustness checks:
- [ ] Caliper sensitivity (try narrower/wider)
- [ ] Neighbor count sensitivity (1 vs 5 neighbors)
- [ ] Alternative matching method (PSM vs CEM)
---
Survey Checklist
Required in methods section:
- [ ]
svysetstatement with PSU, strata, weights
Report in results:
- [ ] Weighted descriptive statistics
- [ ] Key model with survey-corrected SEs
- [ ] Note: "Analyses account for complex survey design"
Important notes:
- [ ] Use
subpop()notiffor subgroup analyses - [ ] Comparison with unweighted results (as robustness, not truth)
---
Synthetic Control Checklist
Required in methods section:
- [ ] Donor pool definition (which units? why these?)
- [ ] Predictor variable rationale
Report in results:
- [ ] Pre-period fit (RMSPE)
- [ ] Unit weights table (which donors contribute?)
- [ ] Gap plot (treated - synthetic over time)
Robustness checks:
- [ ] In-space placebo tests (run synth for each control unit)
- [ ] In-time placebo tests (fake treatment at earlier time)
- [ ] Predictor set sensitivity
- [ ] Exclude potentially contaminated donors
Survey & Resampling Methods in Stata
Survey weights, bootstrap, randomization inference, and decomposition. All code tested on Stata 15+.
---
1. Survey Methods
Setup Survey Design
* Using nhanes2f dataset as example
webuse nhanes2f, clear
* Setup: psuid = PSU, stratid = stratum, finalwgt = weight
svyset psuid [pweight=finalwgt], strata(stratid)Check Survey Setup
svydescribeSurvey-Weighted Estimation
* Survey mean
svy: mean height weight
* Survey mean by group
svy: mean height, over(sex)
* Survey regression
svy: reg height weight age i.sex
* Survey logit
svy: logit highbp age i.sex weightSubpopulation Analysis
Correct way to analyze subgroups (maintains correct SEs):
* Analyze females only
svy, subpop(female): mean height weight
* Analyze using if condition
svy, subpop(if age >= 40): mean bpsystolNote: Always use subpop() rather than if for survey data to get correct variance estimates.
---
2. Bootstrap Methods
Standard Bootstrap
sysuse auto, clear
* Bootstrap standard errors for all coefficients
bootstrap _b, reps(500) seed(12345): reg price mpg weight foreign
* Bootstrap specific statistic
bootstrap diff = (_b[foreign]), reps(500) seed(12345): ///
reg price mpg weight foreignBootstrap Options
| Option | Purpose |
|---|---|
reps(#) | Number of replications |
seed(#) | Random seed for reproducibility |
bca | Bias-corrected accelerated CIs |
strata(var) | Stratified resampling |
cluster(var) | Cluster resampling |
---
3. Wild Cluster Bootstrap
For inference with few clusters (< 40):
* Create clustered data
clear
set seed 12345
set obs 500
gen state = ceil(_n/50)
gen treat = (state <= 5)
gen x = rnormal()
gen y = 1 + 0.5*treat + 0.3*x + rnormal(0, 1)
* Standard clustered SE
reg y treat x, cluster(state)
* Wild cluster bootstrap
boottest treat, cluster(state) reps(999) seed(12345) nographOutput includes:
- Bootstrap t-statistic
- Bootstrap p-value
- 95% confidence interval robust to few clusters
---
4. Randomization Inference
* Create experimental data
clear
set seed 12345
set obs 200
gen id = _n
gen block = ceil(_n/20)
gen treat = mod(_n, 2)
gen y = 1 + 0.5*treat + rnormal(0, 1)
* Standard OLS
reg y treat, robust
* Randomization inference with stratification
ritest treat _b[treat], reps(500) seed(12345) strata(block): ///
reg y treat, robustOutput shows:
- Observed coefficient
- Number of permutations where |T| >= |T(obs)|
- Exact p-value from permutation distribution
---
5. Oaxaca-Blinder Decomposition
* Use nlsw88 data
sysuse nlsw88, clear
keep if !missing(wage, union, age, grade, tenure)
* Basic decomposition by union status
oaxaca wage age grade tenure, by(union)
* Detailed decomposition
oaxaca wage age grade tenure, by(union) detail
* Pooled reference coefficients
oaxaca wage age grade tenure, by(union) pooledInterpretation
The output shows:
- Endowments: Differences due to characteristics (what if Group 2 had Group 1's X values)
- Coefficients: Differences due to returns to characteristics (unexplained/discrimination)
- Interaction: Combined effect
---
Quick Reference
Survey Commands
| Command | Purpose |
|---|---|
svyset | Define survey design |
svy: | Prefix for survey estimation |
svydescribe | Describe survey design |
subpop() | Analyze subpopulation |
Resampling Commands
| Command | Purpose |
|---|---|
bootstrap | Standard bootstrap |
boottest | Wild cluster bootstrap |
ritest | Randomization inference |
Package Installation
ssc install boottest, replace
ssc install ritest, replace
ssc install oaxaca, replaceSynthetic Control Methods in Stata
Synthetic control method for comparative case studies. All code tested on Stata 15+.
---
1. Overview
The synthetic control method constructs a weighted combination of control units to serve as a counterfactual for a treated unit. It is designed for:
- Single treated unit
- Aggregate-level data (states, countries, regions)
- Clear treatment timing
- Multiple potential control units
---
2. Data Requirements
Panel data structure with:
- Unit identifier
- Time variable
- Outcome variable
- Predictor variables
* Declare panel structure
tsset unit_id time_var---
3. Basic Synthetic Control
* Install synth package
ssc install synth, replace
* Basic syntax
synth outcome_var predictors, ///
trunit(#) trperiod(#)Example with Simulated Data
clear
set seed 12345
set obs 400
* Create panel: 20 states, 20 years each
gen state = ceil(_n/20)
bysort state: gen year = 1980 + _n
* Outcome variable
gen y = 100 + state*2 + year*0.5 + rnormal(0, 5)
* Treatment: state 1 treated after year 1990
replace y = y - 15 if state == 1 & year >= 1990
* Covariates
gen x1 = rnormal(50, 10)
gen x2 = rnormal(1000, 200)
* Declare panel
tsset state year
* Run synthetic control
synth y x1 x2 y(1985) y(1988), trunit(1) trperiod(1990)---
4. Specifying Predictors
Average of Variable Over Pre-Period
* x1 averaged over all pre-treatment periods
synth y x1 x2, trunit(1) trperiod(1990)Specific Year Values
* y at specific years as predictors
synth y y(1985) y(1988), trunit(1) trperiod(1990)Range of Years
* y averaged over 1985-1988
synth y y(1985(1)1988), trunit(1) trperiod(1990)Combined Predictors
synth y x1 x2 y(1985) y(1988), trunit(1) trperiod(1990)---
5. Output Interpretation
The synth output shows:
RMSPE (Root Mean Squared Prediction Error)
- Measures pre-treatment fit
- Lower is better
Unit Weights
- Which control units comprise the synthetic control
- Weights sum to 1
Predictor Balance
- Compares treated vs synthetic control on predictors
- Should be similar if fit is good
---
6. Options
| Option | Purpose |
|---|---|
trunit(#) | Treated unit ID |
trperiod(#) | First treatment period |
fig | Display results figure |
keep(filename) | Save results to file |
nested | Use nested optimization |
allopt | Try all optimization methods |
---
7. Inference
Placebo Tests (In-Space)
Run synth for each control unit as if it were treated:
* Store treated unit result
synth y x1 x2 y(1985) y(1988), trunit(1) trperiod(1990) ///
keep(synth_treated) replace
* Placebo for control unit 2
synth y x1 x2 y(1985) y(1988), trunit(2) trperiod(1990) ///
keep(synth_placebo2) replace
* Compare RMSPEs
* Treated effect is significant if RMSPE ratio is largePlacebo Tests (In-Time)
Apply treatment at different (fake) times:
* True treatment 1990
synth y x1 x2 y(1982) y(1985), trunit(1) trperiod(1990)
* Placebo: treatment at 1985 (before actual treatment)
synth y x1 x2 y(1982), trunit(1) trperiod(1985)---
8. Limitations
- Single treated unit (not for multiple treatment)
- Requires good pre-treatment fit
- Sensitive to predictor choice
- No built-in inference (must do placebo tests)
- Cannot extrapolate beyond donor pool characteristics
---
Quick Reference
Basic Syntax
synth outcome predictors, trunit(#) trperiod(#)Package Installation
ssc install synth, replaceKey Components
| Component | Description |
|---|---|
outcome | Dependent variable |
predictors | Variables to match on |
trunit() | ID of treated unit |
trperiod() | First treatment period |
Visualization & Output in Stata
Publication-quality tables, coefficient plots, and figures. All code tested on Stata 15+.
---
1. Regression Tables with esttab
Basic Table
* Run and store models
quietly reg price mpg
estimates store m1
quietly reg price mpg weight
estimates store m2
quietly reg price mpg weight foreign
estimates store m3
* Basic table
esttab m1 m2 m3, se star(* 0.10 ** 0.05 *** 0.01)Publication-Ready Table
esttab m1 m2 m3, ///
se star(* 0.10 ** 0.05 *** 0.01) ///
mtitle("Model 1" "Model 2" "Model 3") ///
title("Price Regressions") ///
keep(mpg weight foreign) ///
order(foreign mpg weight)Export to File
* Text file
esttab m1 m2 m3 using "table1.txt", replace ///
se star(* 0.10 ** 0.05 *** 0.01) ///
mtitle("Model 1" "Model 2" "Model 3")
* LaTeX
esttab m1 m2 m3 using "table1.tex", replace ///
se star(* 0.10 ** 0.05 *** 0.01) ///
booktabs label
* RTF (Word-compatible)
esttab m1 m2 m3 using "table1.rtf", replace ///
se star(* 0.10 ** 0.05 *** 0.01)Common esttab Options
| Option | Description |
|---|---|
se | Show standard errors |
t | Show t-statistics |
p | Show p-values |
ci | Show confidence intervals |
star(...) | Define significance stars |
mtitle(...) | Column titles |
title(...) | Table title |
keep(...) | Variables to show |
drop(...) | Variables to hide |
order(...) | Variable order |
label | Use variable labels |
booktabs | LaTeX booktabs format |
replace | Overwrite existing file |
---
2. Coefficient Plots
Basic Coefficient Plot
* After running regression
reg price mpg weight foreign i.rep78
* Plot coefficients
coefplot, drop(_cons) xline(0) ///
title("Coefficient Plot")
graph export "coefplot.png", replaceMultiple Model Comparison
* Store multiple models first
quietly reg price mpg
estimates store m1
quietly reg price mpg weight
estimates store m2
quietly reg price mpg weight foreign
estimates store m3
* Compare in single plot
coefplot m1 m2 m3, drop(_cons) xline(0) ///
legend(order(2 "Model 1" 4 "Model 2" 6 "Model 3"))
graph export "coefplot_comparison.png", replaceVertical Coefficient Plot
coefplot m3, drop(_cons) vertical ///
yline(0, lpattern(dash)) ///
title("Vertical Coefficient Plot")Event Study Style Plot
* After event study regression with lead/lag dummies
coefplot, keep(lead_* lag_*) vertical ///
yline(0, lpattern(dash)) ///
xline(0.5, lpattern(dash) lcolor(red)) ///
xlabel(, angle(45)) ///
xtitle("Event Time") ytitle("Effect")Customizing coefplot
coefplot m1 m2, drop(_cons) xline(0) ///
ciopts(recast(rcap)) /// // Cap ends on CI
msymbol(D) /// // Diamond markers
mcolor(navy) /// // Marker color
levels(95 90) /// // Multiple CI levels
legend(order(1 "95% CI" 2 "90% CI"))---
3. Summary Statistics
Basic Summary
summarize price mpg weight
* Detailed with percentiles
summarize price, detailtabstat (Formatted)
* Multiple statistics
tabstat price mpg weight, stat(mean sd min max n) columns(statistics)
* By group
tabstat price mpg weight, by(foreign) stat(mean sd n)Summary Table with estpost
* Summary statistics table
estpost summarize price mpg weight
esttab, cells("mean(fmt(2)) sd(fmt(2)) min max count") nomtitle nonumber
* Export to file
esttab using "summary_stats.tex", replace ///
cells("mean(fmt(2)) sd(fmt(2)) min max count") ///
nomtitle nonumber booktabsBalance Table
* By treatment group
bysort treatment: summarize y x1 x2
* Or use tabstat
tabstat y x1 x2, by(treatment) stat(mean sd n) nototal---
4. Basic Graphs
Scatter Plot with Fit Line
twoway (scatter y x) (lfit y x), ///
title("Scatter with Linear Fit") ///
xtitle("X Variable") ytitle("Y Variable") ///
legend(off)
graph export "scatter.png", replaceBinned Scatter (binscatter)
* Install: ssc install binscatter
binscatter y x, controls(z1 z2) ///
title("Binned Scatter") ///
xtitle("X") ytitle("Y | Controls")Time Series
twoway line y year, ///
title("Outcome Over Time") ///
xtitle("Year") ytitle("Outcome")
* Multiple series
twoway (line y1 year) (line y2 year), ///
legend(order(1 "Series 1" 2 "Series 2"))Histogram
histogram y, frequency ///
title("Distribution of Y") ///
xtitle("Y") ytitle("Frequency")Kernel Density
kdensity y, ///
title("Density of Y") ///
xtitle("Y") ytitle("Density")
* By group
twoway (kdensity y if treat==0) (kdensity y if treat==1), ///
legend(order(1 "Control" 2 "Treatment"))---
5. Graph Formatting
Publication Scheme
* Set clean scheme
set scheme s1mono // Black and white
set scheme s1color // Color version
* Or use custom
ssc install grstyle, replace
ssc install palettes, replace
ssc install colrspace, replace
grstyle init
grstyle set plain
grstyle set legend 6, nobox
grstyle set color navy maroon forest_greenCommon Graph Options
twoway ..., ///
title("Main Title") ///
subtitle("Subtitle") ///
xtitle("X Axis Label") ///
ytitle("Y Axis Label") ///
xlabel(0(10)100) /// // X ticks at 0,10,20,...,100
ylabel(, angle(horizontal)) /// // Horizontal Y labels
legend(order(1 "First" 2 "Second") pos(6)) /// // Bottom legend
note("Note: Sample description") ///
graphregion(color(white)) /// // White background
plotregion(margin(zero)) // No marginsExport Formats
* PNG (web/slides)
graph export "figure.png", replace width(2400)
* PDF (publication)
graph export "figure.pdf", replace
* EPS (LaTeX)
graph export "figure.eps", replaceCombine Multiple Graphs
* Create individual graphs
twoway scatter y1 x, name(g1, replace) title("Panel A")
twoway scatter y2 x, name(g2, replace) title("Panel B")
* Combine
graph combine g1 g2, rows(1) ///
title("Combined Figure")
graph export "combined.png", replace---
6. RD Plots (Stata 16+)
* Using rdplot (requires rdrobust package)
rdplot y running_var, c(0) ///
graph_options(title("RD Plot") ///
xtitle("Running Variable") ///
ytitle("Outcome"))---
Quick Reference
Table Output Commands
| Command | Purpose |
|---|---|
esttab | Regression tables |
estpost | Post results for tables |
tabstat | Summary statistics |
tabout | Cross-tabulations |
Graph Commands
| Command | Purpose |
|---|---|
coefplot | Coefficient plots |
binscatter | Binned scatter plots |
twoway | General 2D graphs |
histogram | Histograms |
kdensity | Kernel density |
graph combine | Multi-panel figures |
Export Checklist
- [ ] Use vector format (PDF/EPS) for line plots
- [ ] Use 300+ DPI for raster images
- [ ] Include informative axis labels
- [ ] Add reference lines where appropriate
- [ ] Use consistent color scheme
- [ ] Match journal font requirements
Best Practices for Stata Projects
Code organization, reproducibility, and style conventions based on top journal replication packages.
---
1. Master Do-File Structure
Every project should have a single master script that runs the entire analysis.
Template
* ===========================================================================
* Master Do-File
*
* "[Paper Title]"
* [Authors]
* [Journal], [Year]
*
* ===========================================================================
version 15
clear all
set more off
set maxvar 10000
* ===========================================================================
* PATH SETUP - Edit this section only
* ===========================================================================
* Set root path (CHANGE THIS for your machine)
global root "/path/to/replication"
* Derived paths (do not edit)
global code "$root/code"
global data "$root/data"
global raw "$data/raw"
global clean "$data/clean"
global out "$root/output"
global figures "$out/figures"
global tables "$out/tables"
global logs "$out/logs"
* ===========================================================================
* EXECUTION
* ===========================================================================
log using "$logs/replication_log.txt", text replace
* Data preparation
do "$code/01_import_data.do"
do "$code/02_clean_data.do"
do "$code/03_create_variables.do"
* Analysis
do "$code/10_descriptives.do" // Table 1, Figures 1-2
do "$code/11_main_analysis.do" // Tables 2-4
do "$code/12_robustness.do" // Appendix Tables A1-A5
* Figures
do "$code/20_figures.do" // Figures 3-6
log close
exit---
2. Project Directory Structure
project/
├── code/
│ ├── 00_master.do
│ ├── 01_import_data.do
│ ├── 02_clean_data.do
│ ├── 03_create_variables.do
│ ├── 10_descriptives.do
│ ├── 11_main_analysis.do
│ └── 20_figures.do
├── data/
│ ├── raw/ # Original, unchanged data
│ └── clean/ # Processed data files
├── output/
│ ├── figures/
│ ├── tables/
│ └── logs/
└── README.md---
3. Path Management
Good: Single Root Variable
* Set root path (only line to change)
global root "/Users/name/project"
* Derived paths
global code "$root/code"
global raw "$root/data/raw"
global clean "$root/data/clean"
global figures "$root/output/figures"
global tables "$root/output/tables"Bad: Hardcoded Paths
* DON'T do this - not portable
use "/Users/name/Documents/project/data/mydata.dta"---
4. Data Cleaning Conventions
Recode Missing Values Consistently
* Standardize missing values
recode var1 var2 var3 (9999 = .) (-99 = .) (-1 = .)
* Document recoding with comments
* Original codes: 9999=DK, -99=Refused, -1=NA
recode satisfaction (9999 = .) (-99 = .) (-1 = .)Label Everything
* Define value labels
label define yesno 0 "No" 1 "Yes"
label values treated yesno
* Variable labels
label variable treated "Treatment indicator"
label variable outcome "Primary outcome measure"Check Merge Results
merge m:1 id using "$clean/demographics.dta"
* Document merge results
tab _merge
* Handle unmatched explicitly
assert _merge != 2 // No unmatched from using
drop if _merge == 2
drop _merge---
5. Reproducibility Essentials
Set Random Seed
* Set seed at the beginning of the do-file
set seed 12345 // Use meaningful seed (e.g., date: 20240115)Version Control
* Specify Stata version at top of do-file
version 15
* Record session info
display "Stata version: " c(stata_version)
display "Date: " c(current_date)
display "Time: " c(current_time)Use Log Files
* Start log
log using "$logs/analysis_log.txt", text replace
* ... analysis code ...
log close---
6. Code Style Conventions
Naming
* Variables: snake_case
gen treatment_effect = ...
gen log_income = log(income)
* Wave indicators: suffix with number
rename income incomeW1
rename income2 incomeW2
* Temporary variables: prefix with underscore
gen _temp_var = ...
drop _temp_varComments
* Single-line comment for brief notes
/*
Multi-line comment for
longer explanations
*/
// Alternative single-line (less common in published code)
*--- Section break ---*Line Continuation
* Use /// for long commands
reghdfe outcome treatment control1 control2 control3 ///
control4 control5, ///
absorb(id year) cluster(id)---
7. Analysis Do-File Template
* ===========================================================================
* [Descriptive title]
*
* Purpose: [What this file does]
* Input: [Input data files]
* Output: [Output files - tables, figures]
*
* ===========================================================================
* Load data
use "$clean/analysis_sample.dta", clear
* -------------------------------------------
* Section 1: [Description]
* -------------------------------------------
[analysis code]
* -------------------------------------------
* Section 2: [Description]
* -------------------------------------------
[analysis code]
* -------------------------------------------
* Export results
* -------------------------------------------
esttab m1 m2 m3 using "$tables/table_1.tex", replace ///
[options]
graph export "$figures/figure_1.pdf", replace---
8. Common Patterns
Loop Over Variables
* Process multiple variables
foreach var in income education age {
gen log_`var' = log(`var')
label variable log_`var' "Log `var'"
}Loop Over Specifications
* Multiple model specifications
local controls1 "x1 x2"
local controls2 "x1 x2 x3 x4"
local controls3 "x1 x2 x3 x4 x5 x6"
forvalues i = 1/3 {
reg y treat `controls`i'', robust
estimates store m`i'
}
esttab m1 m2 m3Store Multiple Models Efficiently
* Clear stored estimates
estimates clear
* Run and store
foreach outcome in y1 y2 y3 {
quietly reg `outcome' treat x1 x2, robust
estimates store m_`outcome'
}
* Combined table
esttab m_y1 m_y2 m_y3, se---
9. Pre-Submission Checklist
Code Quality
- [ ] Master script runs entire analysis without errors
- [ ] All paths are relative (single root variable)
- [ ] Random seeds are set and documented
- [ ] Code files have clear headers with purpose
Documentation
- [ ] README documents execution order
- [ ] README lists software/package requirements
- [ ] Output files are named to match paper elements
Reproducibility
- [ ] Stata version specified
- [ ] Package versions recorded
- [ ] Intermediate datasets saved
- [ ] Log files generated
Data
- [ ] Raw data unchanged
- [ ] All data transformations documented
- [ ] Missing value handling explicit
- [ ] Merge results verified
---
Quick Reference
Essential Setup Commands
clear all
set more off
set maxvar 10000
version 15Global Structure
global root "/path/to/project"
global code "$root/code"
global data "$root/data"
global out "$root/output"Output Mapping Comment Style
do "$code/10_analysis.do" // Table 1, Figure 2Modeling Basics in Stata
Plain-vanilla regression and GLM patterns that sociologists use constantly. All code tested on Stata 15+.
---
1. OLS Foundation
Basic OLS with Robust SEs
sysuse auto, clear
* Robust (heteroskedasticity-consistent) standard errors
reg price mpg weight, robustClustered Standard Errors
* Cluster at the group level
reg price mpg weight, cluster(foreign)
* For panel data, typically cluster on the panel unit
reg y x1 x2, cluster(state)Nested Controls Pattern
Build models incrementally to show robustness:
* Model 1: Baseline
reg price mpg, robust
estimates store m1
* Model 2: Add controls
reg price mpg weight, robust
estimates store m2
* Model 3: Add categorical
reg price mpg weight i.foreign, robust
estimates store m3
* Model 4: Full specification
reg price mpg weight i.foreign headroom trunk, robust
estimates store m4
* Display nested table
esttab m1 m2 m3 m4, se star(* 0.10 ** 0.05 *** 0.01) ///
mtitles("(1)" "(2)" "(3)" "(4)") ///
drop(0.foreign) ///
stats(N r2, labels("N" "R-squared") fmt(%9.0fc %9.3f))---
2. Interactions and Margins
Continuous × Continuous Interaction
* c. prefix for continuous variables
reg price c.mpg##c.weight, robust
* Marginal effect of mpg at different weight levels
margins, dydx(mpg) at(weight=(2000 3000 4000))Interpretation note: The interaction coefficient alone doesn't tell you the effect at any particular point. Always use margins to interpret.
Categorical × Continuous Interaction
* i. prefix for categorical variables
reg price i.foreign##c.mpg, robust
* Effect of mpg by foreign status
margins foreign, dydx(mpg)
* Predicted values at specific mpg levels by group
margins foreign, at(mpg=(15 20 25 30))Marginsplot for Visualization
reg price i.foreign##c.mpg, robust
margins foreign, at(mpg=(15(5)35))
marginsplot, title("Price by MPG and Origin") ///
ytitle("Predicted Price") xtitle("MPG")
graph export "$figures/interaction_plot.png", replaceReviewer-Proof Guidelines
- Don't interpret raw interaction coefficient alone - always compute marginal effects
- Plot predicted values - reviewers want to see the interaction visually
- Report at meaningful values - use means or policy-relevant cutpoints
---
3. Binary Outcomes: Logit/Probit
Logit with Robust SEs
sysuse nlsw88, clear
keep if !missing(union, wage, age, grade, tenure)
logit union wage age grade, robust
estimates store logit1Probit Alternative
probit union wage age grade, robust
estimates store probit1
* Compare
esttab logit1 probit1, se star(* 0.10 ** 0.05 *** 0.01) ///
mtitles("Logit" "Probit")Average Marginal Effects (AME)
This is what most sociologists should report:
logit union wage age grade, robust
margins, dydx(*)Interpretation: "A one-unit increase in wage is associated with a 1.25 percentage point increase in the probability of union membership."
Predicted Probabilities at Specific Values
* Probability at specific covariate values
margins, at(wage=(5 10 15) age=35 grade=12)Odds Ratios
* Report odds ratios instead of coefficients
logit union wage age grade, orInterpretation: Odds ratio of 1.07 means "each dollar increase in wage is associated with 7% higher odds of union membership."
Choosing What to Report
| Format | When to Use |
|---|---|
| Marginal effects | Most journal articles; easy to interpret |
| Odds ratios | Clinical/epidemiological conventions |
| Raw coefficients | Technical appendix; rarely main table |
Goodness-of-Fit Notes
- Pseudo-R² is not R² - don't interpret as variance explained
- Classification tables are optional - not decisive for model quality
- Focus on coefficient interpretation, not fit statistics
---
4. Count Models: Poisson and Negative Binomial
When to Use Which
- Poisson: Counts with variance ≈ mean (equidispersion)
- Negative Binomial: Counts with variance > mean (overdispersion)
- Rule of thumb: If variance >> mean, use negative binomial
Poisson with Robust SEs
poisson y_count x1 x2, robust
estimates store pois1
* Predicted counts
margins, at(x1=(-1 0 1) x2=0)Negative Binomial
nbreg y_count x1 x2, robust
estimates store nb1
* Compare Poisson vs NB
esttab pois1 nb1, se star(* 0.10 ** 0.05 *** 0.01) ///
mtitles("Poisson" "Neg Binomial")Incidence Rate Ratios
poisson y_count x1 x2, irrInterpretation: IRR of 1.33 means "a one-unit increase in x1 is associated with 33% more events."
---
5. Ordinal Outcomes
Ordered Logit
sysuse auto, clear
* rep78 is 1-5 repair record
ologit rep78 price mpg foreign, robustPredicted Probabilities by Category
* Probability of being in category 1
margins, predict(outcome(1))
* Probability of being in category 5
margins, predict(outcome(5))
* Predicted probabilities for all categories
margins, predict(outcome(1)) predict(outcome(2)) predict(outcome(3)) ///
predict(outcome(4)) predict(outcome(5))---
6. Multilevel Models (Optional)
Use when you have hierarchical data (students in schools, respondents in states) and theory suggests random effects.
Random Intercept (Linear)
* Students (i) nested in schools (j)
mixed test_score ses || school:Random Intercept (Binary)
* Binary outcome with random intercepts
melogit graduated ses || school:Key Distinction
- Cluster-robust SEs: Adjusts SEs for clustering; coefficients are population-averaged
- Multilevel models: Explicitly models variance at each level; coefficients are conditional on random effects
Choose based on your research question and theory, not convenience.
---
7. Diagnostics
Multicollinearity
reg price mpg weight length, robust
estat vifRule of thumb: VIF > 10 suggests problematic collinearity.
Influential Observations
reg price mpg weight
* Leverage (unusual X values)
predict leverage, leverage
gen high_leverage = leverage > 2*(3+1)/74 // 2*(k+1)/n
* Cook's Distance (influential points)
predict cooksd, cooksd
gen influential = cooksd > 4/74 // 4/n
tab high_leverage
tab influentialResidual Plots
reg price mpg weight, robust
predict resid, residual
predict yhat, xb
* Histogram of residuals
histogram resid, normal title("Residual Distribution")
graph export "$figures/residual_hist.png", replace
* Residual vs fitted
scatter resid yhat, yline(0, lpattern(dash)) ///
title("Residuals vs Fitted")
graph export "$figures/resid_fitted.png", replace---
Quick Reference
OLS Variants
| Task | Command |
|---|---|
| Robust SE | reg y x, robust |
| Clustered SE | reg y x, cluster(id) |
| Two-way cluster | reghdfe y x, cluster(id time) |
Binary Models
| Task | Command |
|---|---|
| Logit | logit y x, robust |
| Probit | probit y x, robust |
| Odds ratios | logit y x, or |
| Marginal effects | margins, dydx(*) |
Count Models
| Task | Command |
|---|---|
| Poisson | poisson y x, robust |
| Negative binomial | nbreg y x, robust |
| IRR | poisson y x, irr |
Margins Commands
| Task | Command |
|---|---|
| AME for all | margins, dydx(*) |
| At specific values | margins, at(x=(1 2 3)) |
| By group | margins group, dydx(x) |
| Plot | marginsplot |
Post-Estimation and Reporting in Stata
What you do after you estimate—so outputs match journal expectations. All code tested on Stata 15+.
---
1. Estimates Workflow
Store Results
sysuse auto, clear
reg price mpg, robust
estimates store base
reg price mpg weight, robust
estimates store controls1
reg price mpg weight i.foreign, robust
estimates store controls2
reg price mpg weight i.foreign headroom trunk, robust
estimates store fullList and Retrieve
* List all stored estimates
estimates dir
* Replay a specific model
estimates replay controls1
* Restore for post-estimation commands
estimates restore full
display "R-squared: " e(r2)Naming Conventions
Use consistent, descriptive names:
| Pattern | Example |
|---|---|
| By specification | base, controls, full |
| By sample | main, robust_sample, placebo |
| By method | ols, iv, matching |
---
2. Nested Tables with esttab
Standard Journal Format
esttab base controls1 controls2 full, ///
se star(* 0.10 ** 0.05 *** 0.01) ///
mtitles("(1)" "(2)" "(3)" "(4)") ///
title("Table 2: Price Determinants") ///
addnotes("Robust standard errors in parentheses") ///
drop(0.foreign) ///
stats(N r2, labels("N" "R-squared") fmt(%9.0fc %9.3f))Export to RTF (Word-Compatible)
esttab base controls1 controls2 full using "$tables/table2_models.rtf", ///
replace ///
se star(* 0.10 ** 0.05 *** 0.01) ///
mtitles("(1)" "(2)" "(3)" "(4)") ///
title("Table 2: Price Determinants") ///
drop(0.foreign) ///
stats(N r2, labels("N" "R-squared") fmt(%9.0fc %9.3f))Export to CSV
esttab base controls1 controls2 full using "$tables/table2_models.csv", ///
replace csv ///
se star(* 0.10 ** 0.05 *** 0.01)Export to LaTeX
esttab base controls1 controls2 full using "$tables/table2_models.tex", ///
replace booktabs ///
se star(* 0.10 ** 0.05 *** 0.01) ///
mtitles("(1)" "(2)" "(3)" "(4)") ///
drop(0.foreign) ///
stats(N r2, labels("N" "R-squared") fmt(%9.0fc %9.3f))---
3. Predicted Values and Effects
Predicted Values for Hypothetical Cases
reg price mpg weight i.foreign, robust
* Domestic car with mpg=20, weight=3000
margins, at(mpg=20 weight=3000 foreign=0)
* Foreign car with same specs
margins, at(mpg=20 weight=3000 foreign=1)Save Predictions to Data
reg price mpg weight i.foreign, robust
predict yhat, xb // predicted values
predict resid, residual // residuals
summarize price yhat residMarginal Effects for Presentation
logit union wage age grade, robust
* Average marginal effects
margins, dydx(*)
* Save to matrix for export
margins, dydx(*) post
esttab, cells("b(fmt(4)) se(fmt(4)) p(fmt(3))") ///
title("Average Marginal Effects")Marginsplot
reg price i.foreign##c.mpg, robust
margins foreign, at(mpg=(15(5)35))
marginsplot, title("Predicted Price by MPG and Origin") ///
ytitle("Predicted Price ($)") xtitle("Miles per Gallon")
graph export "$figures/figure1_margins.png", replace---
4. Model Diagnostics
Multicollinearity (VIF)
reg price mpg weight length, robust
estat vif| VIF | Interpretation |
|---|---|
| < 5 | Generally acceptable |
| 5-10 | Moderate concern |
| > 10 | High collinearity |
Influential Points
reg price mpg weight
predict leverage, leverage
predict cooksd, cooksd
* Flag problematic observations
gen high_leverage = leverage > 2*(3+1)/_N // 2*(k+1)/n rule
gen influential = cooksd > 4/_N // 4/n rule
tab high_leverage
tab influential
list make price mpg weight if influential == 1Residual Diagnostics
reg price mpg weight, robust
predict resid, residual
predict yhat, xb
* Residual histogram
histogram resid, normal title("Residual Distribution")
graph export "$figures/residual_hist.png", replace
* Residual vs fitted plot
scatter resid yhat, yline(0, lpattern(dash)) ///
title("Residuals vs Fitted Values")
graph export "$figures/resid_fitted.png", replaceHeteroskedasticity
Robust SEs handle this, but to test formally:
reg price mpg weight
estat hettest---
5. Table 1: Descriptive Statistics
Overall Summary
tabstat price mpg weight, stat(n mean sd min max) col(stat)Summary by Group
tabstat price mpg weight, by(foreign) stat(n mean sd) nototalPublication-Ready Table 1
* Using estpost + esttab
estpost summarize price mpg weight length
esttab, cells("count mean(fmt(2)) sd(fmt(2)) min max") ///
nomtitle nonumber title("Table 1: Descriptive Statistics")Export Summary Statistics
estpost summarize price mpg weight length
esttab using "$tables/table1_descriptives.rtf", ///
replace ///
cells("count mean(fmt(2)) sd(fmt(2)) min max") ///
nomtitle nonumber ///
title("Table 1: Descriptive Statistics")---
6. Balance Tables
For treatment/control comparisons:
Simple Balance Check
* Means by treatment
tabstat mpg weight length, by(treat) stat(mean sd) nototalT-Tests for Differences
ttest mpg, by(treat)
ttest weight, by(treat)
ttest length, by(treat)Formal Balance Table
* Create treatment indicator
gen treat = (price > 6000)
* Compare means and run t-tests
foreach var in mpg weight length {
display ""
display "=== `var' ==="
ttest `var', by(treat)
}---
7. Output Naming Conventions
Standard File Names
* Tables
"$tables/table1_descriptives.rtf"
"$tables/table2_main_models.rtf"
"$tables/table3_robustness.rtf"
"$tables/tableA1_balance.rtf" // appendix
* Figures
"$figures/figure1_trends.png"
"$figures/figure2_event_study.png"
"$figures/figureA1_placebo.png" // appendixIn-Code Documentation
* ===================================
* Table 2: Main Regression Results
* ===================================
reg price mpg weight i.foreign, robust
estimates store m1
// ... more models
esttab m1 m2 m3 using "$tables/table2_main_models.rtf", replace ...---
8. Complete Output Workflow Example
* ===========================================================================
* Output Generation Script
* ===========================================================================
clear all
set more off
use "$clean/analysis_sample.dta", clear
* -----------------------------------
* Table 1: Descriptive Statistics
* -----------------------------------
estpost summarize price mpg weight length
esttab using "$tables/table1_descriptives.rtf", replace ///
cells("count mean(fmt(2)) sd(fmt(2)) min max") nomtitle nonumber
* -----------------------------------
* Table 2: Main Models
* -----------------------------------
reg price mpg, robust
estimates store m1
reg price mpg weight, robust
estimates store m2
reg price mpg weight i.foreign, robust
estimates store m3
esttab m1 m2 m3 using "$tables/table2_main_models.rtf", replace ///
se star(* 0.10 ** 0.05 *** 0.01) ///
mtitles("(1)" "(2)" "(3)") ///
stats(N r2, labels("N" "R-squared") fmt(%9.0fc %9.3f))
* -----------------------------------
* Figure 1: Coefficient Plot
* -----------------------------------
reg price mpg weight headroom trunk length, robust
coefplot, drop(_cons) xline(0) ///
title("Coefficient Estimates")
graph export "$figures/figure1_coef_plot.png", replace
display "Output generation complete!"---
Quick Reference
esttab Options
| Option | Purpose |
|---|---|
se | Show standard errors |
star(* .10 ** .05 *** .01) | Significance stars |
mtitles() | Column titles |
drop() | Omit variables |
stats(N r2) | Add statistics |
replace | Overwrite file |
Export Formats
| Format | Command |
|---|---|
| RTF (Word) | using "file.rtf" |
| CSV | using "file.csv", csv |
| LaTeX | using "file.tex", booktabs |
| Screen | no using clause |
Margins Commands
| Task | Command |
|---|---|
| Average marginal effects | margins, dydx(*) |
| At specific values | margins, at(x=(1 2 3)) |
| Plot | marginsplot |
| Export to table | margins, dydx(*) post then esttab |