Data Analysis Workflow
Run an end-to-end data analysis in R or Python: load, explore, analyze, and produce publication-ready output.
Input: $ARGUMENTS — a dataset path (e.g., data/county_panel.csv) or a description of the analysis goal (e.g., "regress wages on education with state fixed effects using CPS data").
Phase 0: Choose Language
Determine language from $ARGUMENTS or ask the user:
- User mentions
tidyverse, fixest, lm, .R context → R track
- User mentions
pandas, statsmodels, sklearn, .py or .ipynb context → Python track
- Dataset is
.csv/.parquet with no language cue → use AskUserQuestion with a single-select menu:
- header: "Language"
- question: "Which language should I use for this analysis?"
- options:
- label: "R (Recommended)", description: "tidyverse, fixest, ggplot2 — full plugin support with coding conventions and R reviewer"
- label: "Python", description: "pandas, statsmodels — supported for analysis scripts and figures"
- label: "Both", description: "R for figures and tables, Python for data processing"
R Track
Constraints
- Follow
rules/r-code-conventions.md for all standards
- Save scripts to
scripts/R/ with descriptive names
- Save all outputs (figures, tables, RDS) to
output/
- Use
saveRDS() for every computed object
- Run
r-reviewer on the generated script before presenting results
Phase 1: Setup and Data Loading
- Create R script with proper header (title, author, purpose, inputs, outputs)
- Load required packages at top (
library(), never require())
- Set seed once at top:
set.seed(42)
- Create output directories:
dir.create("output/analysis", recursive = TRUE, showWarnings = FALSE)
- Load and inspect the dataset
Phase 2: Exploratory Data Analysis
summary(), missingness rates, variable types
- Histograms for key continuous variables
- Scatter plots, correlation matrices
- Panel trends, pre-treatment comparisons if applicable
- Save all diagnostic figures to
output/diagnostics/
Phase 3: Main Analysis
- Panel data: use
fixest; cross-section: use lm/glm
- Cluster SEs at the appropriate level (document why)
- Multiple specifications: start simple, progressively add controls
- Report standardized effects alongside raw coefficients
Phase 4: Publication-Ready Output
Tables: modelsummary (preferred) or stargazer — export .tex and .html
Figures: ggplot2 with project theme; explicit ggsave(width = X, height = Y); save as .pdf and .png; add bg = "transparent" only if output is for Beamer slides
Phase 5: Save and Review
saveRDS() for all key objects
- Run the
r-reviewer agent: "Review the script at scripts/R/[script_name].R"
- Address Critical and High issues before presenting results
R Script Template
# ============================================================
# [Descriptive Title]
# Author: [from project context]
# Purpose: [What this script does]
# Inputs: [Data files]
# Outputs: [Figures, tables, RDS files]
# ============================================================
# 0. Setup ----
library(tidyverse)
library(fixest)
library(modelsummary)
set.seed(42)
dir.create("output/analysis", recursive = TRUE, showWarnings = FALSE)
# 1. Data Loading ----
# 2. Exploratory Analysis ----
# 3. Main Analysis ----
# 4. Tables and Figures ----
# 5. Export ----
Python Track
Constraints
- Save scripts to
scripts/python/ with descriptive names
- Save all outputs (figures, tables, pickles) to
output/
- Use
joblib.dump() for model objects; .to_parquet() for DataFrames
- Use
pathlib.Path for all file paths — never hardcode absolute paths
- Set random seeds at the top of the script
Phase 1: Setup and Data Loading
- Create Python script with header (title, author, purpose, inputs, outputs)
- Import all packages at the top of the file
- Set seeds:
np.random.seed(42) and random.seed(42)
- Create output directories:
Path("output/analysis").mkdir(parents=True, exist_ok=True)
- Load and inspect the dataset with
pandas
Phase 2: Exploratory Data Analysis
df.describe(), df.isnull().sum(), df.dtypes
- Histograms and distributions with
matplotlib/seaborn
- Scatter plots and correlation matrices
- Save diagnostic figures to
output/diagnostics/
- Save summary stats:
df.describe().to_csv("output/diagnostics/summary_stats.csv")
Phase 3: Main Analysis
- Cross-section OLS:
smf.ols("y ~ x", data=df).fit(cov_type="HC3")
- Panel data:
PanelOLS from linearmodels with cluster-robust SEs
- Multiple specifications: build incrementally
- Document SE choice with a comment
Phase 4: Publication-Ready Output
Tables: Format with pandas and export via .to_latex() or stargazer (Python port)
Figures: matplotlib/seaborn; explicit fig.savefig(path, dpi=300, bbox_inches="tight"); save as .pdf and .png
Phase 5: Save and Review
joblib.dump(model, "output/model.pkl") for fitted models
df_results.to_parquet("output/results.parquet") for DataFrames
- Review the script manually against the Python checklist below before presenting
Python Script Template
# ============================================================
# [Descriptive Title]
# Author: [from project context]
# Purpose: [What this script does]
# Inputs: [Data files]
# Outputs: [Figures, tables, pickle/parquet files]
# ============================================================
import random
import numpy as np
import pandas as pd
import statsmodels.formula.api as smf
import matplotlib.pyplot as plt
import seaborn as sns
import joblib
from pathlib import Path
# Seeds
np.random.seed(42)
random.seed(42)
# Output directories
Path("output/analysis").mkdir(parents=True, exist_ok=True)
Path("output/figures").mkdir(parents=True, exist_ok=True)
# 1. Data Loading
# 2. Exploratory Analysis
# 3. Main Analysis
# 4. Tables and Figures
# 5. Export
Python Quality Checklist
[ ] All imports at top
[ ] Random seeds set (numpy + stdlib)
[ ] All paths use pathlib.Path — no hardcoded strings
[ ] Output directories created with mkdir(exist_ok=True)
[ ] Figures saved with explicit dpi=300, bbox_inches="tight"
[ ] Model objects saved with joblib.dump()
[ ] DataFrames saved as parquet
[ ] Comments explain WHY, not WHAT
Shared Principles
- Reproduce, don't guess. If the user specifies a regression, run exactly that.
- Show your work. Compute summary statistics before jumping to regression.
- Check for issues. Look for multicollinearity, outliers, perfect prediction, missing data.
- Use relative paths. All paths relative to repository root.
- No hardcoded values. Use variables for sample restrictions, date ranges, thresholds.
1---2name: brycewang-stanford-awesome-agent-skills-for-empirical-re-773description: Data Analysis Workflow4---56# Data Analysis Workflow78Run an end-to-end data analysis in R or Python: load, explore, analyze, and produce publication-ready output.910**Input:** `$ARGUMENTS` — a dataset path (e.g., `data/county_panel.csv`) or a description of the analysis goal (e.g., "regress wages on education with state fixed effects using CPS data").1112---1314## Phase 0: Choose Language1516Determine language from `$ARGUMENTS` or ask the user:17- User mentions `tidyverse`, `fixest`, `lm`, `.R` context → **R track**18- User mentions `pandas`, `statsmodels`, `sklearn`, `.py` or `.ipynb` context → **Python track**19- Dataset is `.csv`/`.parquet` with no language cue → use AskUserQuestion with a single-select menu:20 - header: "Language"21 - question: "Which language should I use for this analysis?"22 - options:23 - label: "R (Recommended)", description: "tidyverse, fixest, ggplot2 — full plugin support with coding conventions and R reviewer"24 - label: "Python", description: "pandas, statsmodels — supported for analysis scripts and figures"25 - label: "Both", description: "R for figures and tables, Python for data processing"2627---2829## R Track3031### Constraints32- Follow `rules/r-code-conventions.md` for all standards33- Save scripts to `scripts/R/` with descriptive names34- Save all outputs (figures, tables, RDS) to `output/`35- Use `saveRDS()` for every computed object36- Run `r-reviewer` on the generated script before presenting results3738### Phase 1: Setup and Data Loading391. Create R script with proper header (title, author, purpose, inputs, outputs)402. Load required packages at top (`library()`, never `require()`)413. Set seed once at top: `set.seed(42)`424. Create output directories: `dir.create("output/analysis", recursive = TRUE, showWarnings = FALSE)`435. Load and inspect the dataset4445### Phase 2: Exploratory Data Analysis46- `summary()`, missingness rates, variable types47- Histograms for key continuous variables48- Scatter plots, correlation matrices49- Panel trends, pre-treatment comparisons if applicable50- Save all diagnostic figures to `output/diagnostics/`5152### Phase 3: Main Analysis53- Panel data: use `fixest`; cross-section: use `lm`/`glm`54- Cluster SEs at the appropriate level (document why)55- Multiple specifications: start simple, progressively add controls56- Report standardized effects alongside raw coefficients5758### Phase 4: Publication-Ready Output59**Tables:** `modelsummary` (preferred) or `stargazer` — export `.tex` and `.html`60**Figures:** `ggplot2` with project theme; explicit `ggsave(width = X, height = Y)`; save as `.pdf` and `.png`; add `bg = "transparent"` only if output is for Beamer slides6162### Phase 5: Save and Review631. `saveRDS()` for all key objects642. Run the `r-reviewer` agent: *"Review the script at scripts/R/[script_name].R"*653. Address Critical and High issues before presenting results6667### R Script Template68```r69# ============================================================70# [Descriptive Title]71# Author: [from project context]72# Purpose: [What this script does]73# Inputs: [Data files]74# Outputs: [Figures, tables, RDS files]75# ============================================================7677# 0. Setup ----78library(tidyverse)79library(fixest)80library(modelsummary)8182set.seed(42)83dir.create("output/analysis", recursive = TRUE, showWarnings = FALSE)8485# 1. Data Loading ----86# 2. Exploratory Analysis ----87# 3. Main Analysis ----88# 4. Tables and Figures ----89# 5. Export ----90```9192---9394## Python Track9596### Constraints97- Save scripts to `scripts/python/` with descriptive names98- Save all outputs (figures, tables, pickles) to `output/`99- Use `joblib.dump()` for model objects; `.to_parquet()` for DataFrames100- Use `pathlib.Path` for all file paths — never hardcode absolute paths101- Set random seeds at the top of the script102103### Phase 1: Setup and Data Loading1041. Create Python script with header (title, author, purpose, inputs, outputs)1052. Import all packages at the top of the file1063. Set seeds: `np.random.seed(42)` and `random.seed(42)`1074. Create output directories: `Path("output/analysis").mkdir(parents=True, exist_ok=True)`1085. Load and inspect the dataset with `pandas`109110### Phase 2: Exploratory Data Analysis111- `df.describe()`, `df.isnull().sum()`, `df.dtypes`112- Histograms and distributions with `matplotlib`/`seaborn`113- Scatter plots and correlation matrices114- Save diagnostic figures to `output/diagnostics/`115- Save summary stats: `df.describe().to_csv("output/diagnostics/summary_stats.csv")`116117### Phase 3: Main Analysis118- Cross-section OLS: `smf.ols("y ~ x", data=df).fit(cov_type="HC3")`119- Panel data: `PanelOLS` from `linearmodels` with cluster-robust SEs120- Multiple specifications: build incrementally121- Document SE choice with a comment122123### Phase 4: Publication-Ready Output124**Tables:** Format with `pandas` and export via `.to_latex()` or `stargazer` (Python port)125**Figures:** `matplotlib`/`seaborn`; explicit `fig.savefig(path, dpi=300, bbox_inches="tight")`; save as `.pdf` and `.png`126127### Phase 5: Save and Review1281. `joblib.dump(model, "output/model.pkl")` for fitted models1292. `df_results.to_parquet("output/results.parquet")` for DataFrames1303. Review the script manually against the Python checklist below before presenting131132### Python Script Template133```python134# ============================================================135# [Descriptive Title]136# Author: [from project context]137# Purpose: [What this script does]138# Inputs: [Data files]139# Outputs: [Figures, tables, pickle/parquet files]140# ============================================================141142import random143import numpy as np144import pandas as pd145import statsmodels.formula.api as smf146import matplotlib.pyplot as plt147import seaborn as sns148import joblib149from pathlib import Path150151# Seeds152np.random.seed(42)153random.seed(42)154155# Output directories156Path("output/analysis").mkdir(parents=True, exist_ok=True)157Path("output/figures").mkdir(parents=True, exist_ok=True)158159# 1. Data Loading160# 2. Exploratory Analysis161# 3. Main Analysis162# 4. Tables and Figures163# 5. Export164```165166### Python Quality Checklist167```168[ ] All imports at top169[ ] Random seeds set (numpy + stdlib)170[ ] All paths use pathlib.Path — no hardcoded strings171[ ] Output directories created with mkdir(exist_ok=True)172[ ] Figures saved with explicit dpi=300, bbox_inches="tight"173[ ] Model objects saved with joblib.dump()174[ ] DataFrames saved as parquet175[ ] Comments explain WHY, not WHAT176```177178---179180## Shared Principles181182- **Reproduce, don't guess.** If the user specifies a regression, run exactly that.183- **Show your work.** Compute summary statistics before jumping to regression.184- **Check for issues.** Look for multicollinearity, outliers, perfect prediction, missing data.185- **Use relative paths.** All paths relative to repository root.186- **No hardcoded values.** Use variables for sample restrictions, date ranges, thresholds.