{"id":"490bc560-f3fe-456f-9b9a-92db2c849799","shortId":"Tb6P6v","kind":"skill","title":"statspai","tagline":"Agent-native one-stop toolkit for the full empirical data-analysis pipeline in Python (v1.6+). 390+ functions, one import (`import statspai as sp`), unified API. Covers the complete loop after data cleaning — descriptive stats & EDA (sp.sumstats, sp.balance_table, sp.balance_pane","description":"# StatsPAI: Agent-Native Causal Inference & Econometrics\n\nStatsPAI is the agent-native Python package for causal inference and applied econometrics. One `import statspai as sp`, 390+ functions, covering the complete empirical research workflow.\n\n**Source**: https://github.com/brycewang-stanford/StatsPAI  \n**PyPI**: `pip install statspai`  \n**Paper**: Submitted to Journal of Open Source Software (JOSS) — under review\n\n## Why StatsPAI for Agents?\n\nStatsPAI is the **first econometrics toolkit purpose-built for LLM-driven empirical research**:\n\n1. **Self-describing API**: `sp.list_functions()`, `sp.describe_function(\"did\")`, `sp.function_schema(\"rdrobust\")` — agents discover and understand functions without doc lookup.\n2. **Unified result objects**: Every estimator returns a `CausalResult` with `.summary()`, `.plot()`, `.to_latex()`, `.to_word()`, `.to_excel()`, `.cite()`, and a structured `.diagnostics` dict for agent logic.\n3. **One import covers the full pipeline**: descriptive stats → research-question DSL → DAG discovery → estimation → diagnostics → robustness, all behind `sp.<func>`.\n4. **Estimand-first decisions**: `sp.causal_question` and `sp.causal` make the \"DID vs RD vs IV?\" choice explicit and defensible — not a guess.\n\n## End-to-End Empirical Pipeline (v1.6 P1) — the one-stop flow\n\nThe canonical agent loop, after the dataset is loaded:\n\n```\nStep 0  Data cleaning           pandas (NOT StatsPAI — see Scope below)\nStep 1  EDA & descriptives      sp.sumstats / sp.balance_table / sp.describe\nStep 2  Pre-flight checks       sp.balance_panel / sp.diagnose / overlap & missing\nStep 3  Research question       sp.causal_question(...).identify()\nStep 4  Model exploration       sp.llm_dag_propose → sp.llm_dag_validate → sp.llm_dag_constrained\nStep 5  Estimation              sp.causal(...)  OR  sp.<specific_estimator>(...)\nStep 6  Diagnostics & robust    sp.diagnose / sp.spec_curve / sp.honest_did / sp.evalue\n```\n\n`sp.paper()` exists for end-to-end draft generation but is **out of scope for this skill** — stop at Step 6 and hand the `CausalResult` back to the user.\n\n> **Note on code blocks below.** All Step 0–6 examples share one **labor-economics running narrative** (`training → wage`, with `worker_id` / `firm_id` / `year` / `age` / `edu` / `tenure`) purely for readability. Every column name, `population` string, `estimand`, and `design` value is **illustrative** — agents must substitute the actual columns and design from the user's DataFrame and research question. Only the `sp.*` function names and argument *shapes* are normative.\n\n### Scope boundary — what StatsPAI does NOT do\n\nStatsPAI assumes you arrive with an **analysis-ready DataFrame**. Do these in pandas (or your preferred ETL) *before* calling any `sp.*` function:\n\n```python\nimport pandas as pd\n\ndf = pd.read_csv(\"raw.csv\")\ndf = df.dropna(subset=[\"y\", \"treatment\"])              # missing on key vars\ndf[\"year\"] = pd.to_numeric(df[\"year\"], errors=\"coerce\") # type coercion\ndf = df.merge(covariates, on=\"firm_id\", how=\"left\")    # joins\ndf[\"log_wage\"] = np.log(df[\"wage\"].clip(lower=1))      # transforms\n```\n\nIf the agent skips Step 0 and feeds dirty data into `sp.*`, estimators will either error or silently drop rows — both are bugs you own, not StatsPAI's.\n\n### Step 1 — Descriptive statistics & EDA\n\n```python\nsp.sumstats(df, vars=[\"wage\", \"edu\", \"exp\"], by=\"treated\", output=\"table1.docx\")\nsp.describe(df)                                          # variable labels & types\nsp.balance_table(df, treat=\"treated\",\n                 covariates=[\"age\", \"edu\", \"income\"], test=\"ttest\")  # Table 1\n```\n\n### Step 2 — Pre-flight checks (catch design failures before estimation)\n\n```python\n# Panel structure — balance_panel DROPS unbalanced units (returns the balanced panel)\nbalanced = sp.balance_panel(df, entity=\"firm_id\", time=\"year\")\nif len(balanced) < len(df):\n    print(f\"Dropped {len(df) - len(balanced)} rows from unbalanced units — \"\n          \"decide drop vs keep before DID.\")\n\n# Treatment timing (staggered adoption?)\ndf.groupby(\"first_treat_year\").size()                    # cohort sizes\n\n# Covariate & outcome sanity (generic EDA, returns a dict report)\nreport = sp.diagnose(df, y=\"wage\", x=[\"age\", \"edu\", \"tenure\"])\n# Full identification-level diagnostics (PT, weak IV, overlap, leverage) run\n# automatically inside sp.causal(...) in Step 5 — don't duplicate here.\n```\n\n### Step 3 — Estimand-first research question (the \"DID vs RD vs IV?\" decision)\n\n`sp.causal_question` is the **estimand-first DSL**: declare population, treatment, outcome, estimand, design — then `.identify()` picks the estimator and writes down the assumptions you're committing to. This is the decision layer; `sp.spec_curve` is the *results-layer* multiverse and is not a substitute.\n\n```python\nq = sp.causal_question(\n    treatment=\"training\",\n    outcome=\"wage\",\n    data=df,\n    population=\"manufacturing workers, 2010–2020\",\n    estimand=\"ATT\",\n    design=\"auto\",                # or \"did\" / \"rdd\" / \"iv\" / \"rct\" / \"obs\"\n    time_structure=\"panel\",\n    time=\"year\", id=\"worker_id\",\n    covariates=[\"age\", \"edu\", \"tenure\"],\n)\n\nplan = q.identify()               # IdentificationPlan: estimator + assumptions + fallbacks\nprint(plan)                       # human-readable Methods paragraph\nresult = q.estimate()             # runs the picked estimator\nprint(result.summary())\n```\n\n### Step 4 — Model exploration via LLM-assisted DAG (closed loop)\n\n```python\n# Propose: LLM (or heuristic backend) drafts a DAG from variable names + domain\nproposal = sp.llm_dag_propose(\n    variables=df.columns.tolist(),\n    domain=\"labor economics: training, wages, tenure\",\n    client=my_llm_client,         # any object with .complete(prompt) -> str; None = heuristic\n)\n\n# Validate: per-edge CI test against the data\nvalidation = sp.llm_dag_validate(proposal, df, alpha=0.05)\nprint(validation.edge_evidence)   # which proposed edges the data supports\n\n# Constrained discovery: propose → constrain → CI-validate → demote, until stable\ndiscovered = sp.llm_dag_constrained(\n    df,\n    descriptions={\"wage\": \"monthly wage USD\", \"training\": \"0/1 program\"},\n    oracle=my_llm_client.suggest_edges,   # optional; falls back to plain PC without it\n    max_iter=3,\n)\n```\n\nPass the resulting DAG into `sp.causal(..., dag=discovered.dag)` so identification reasoning uses it.\n\n### Step 5 — Estimation (one-call orchestration OR specific estimator)\n\n**One-call (recommended for agents):**\n```python\nw = sp.causal(df, y=\"wage\", treatment=\"training\",\n              id=\"worker_id\", time=\"year\", design=\"did\",\n              covariates=[\"age\", \"edu\", \"tenure\"],\n              dag=discovered.dag)        # optional\nprint(w.diagnostics)                     # identification verdict\nprint(w.recommendation)                  # which estimator + why\nprint(w.result.summary())                # point estimate + SE + CI\nprint(w.robustness_findings)             # automated robustness battery\n```\n\n**Or call a specific estimator directly** — see \"Method Catalog\" below.\n\n### Step 6 — Diagnostics & robustness\n\n```python\nsp.diagnose_result(result)               # PT / weak-IV / overlap / leverage battery on a fitted result\nsp.honest_did(result, method=\"smoothness\")   # Rambachan–Roth PT sensitivity (DID)\n\n# E-value takes point estimate + CI (or SE), NOT a result object. Extract from .params / .conf_int().\nsp.evalue(estimate=result.params[\"training\"],\n          ci=tuple(result.conf_int().loc[\"training\"]),\n          measure=\"RR\")                  # unmeasured-confounder sensitivity\n\n# Specification curve: controls must be a LIST OF LISTS (each inner list = one spec).\nsp.spec_curve(df, y=\"wage\", x=\"training\",\n              controls=[[\"age\"],\n                        [\"age\", \"edu\"],\n                        [\"age\", \"edu\", \"tenure\"]],\n              subsets={\"all\": None, \"manuf\": df[\"industry\"].eq(\"manufacturing\")})\n\nsp.bacon_decomposition(df, y=\"wage\", treat=\"training\",\n                       time=\"year\", id=\"worker_id\")      # TWFE diagnostic for staggered DID\nsp.estat(result, test=\"all\")                             # Stata-style postestimation (single test name or 'all')\n```\n\n---\n\n## Method Catalog\n\n### Classical Econometrics\n```python\n# regress / ivreg take FORMULA first, then data (statsmodels-style)\nsp.regress(\"y ~ x1 + x2\", df, cluster=\"firm_id\")                     # OLS\nsp.ivreg(\"y ~ (x1 ~ z1 + z2) + x2\", df, cluster=\"state\")             # IV/2SLS — syntax: (endog ~ instruments) + exog\nsp.panel(df, \"y ~ x1 + x2\", entity=\"firm\", time=\"year\", method=\"fe\") # Panel FE (kwarg is `method=`)\nsp.heckman(df, y=\"wage\", x=[\"age\", \"edu\"],                            # Heckman selection\n           select=\"in_labor_force\", z=[\"marital\", \"kids\"])            #   y/x for outcome, select+z for selection\nsp.qreg(df, formula=\"y ~ x1 + x2\", quantile=0.5)                      # Quantile regression\n```\n\n### Difference-in-Differences\n```python\n# 2x2 DID: `time` must take exactly 2 values (a post indicator works).\nsp.did(df, y=\"y\", treat=\"treated\", time=\"post\")\n\n# Staggered DID estimators REQUIRE a unit-id column `i=`.\nsp.callaway_santanna(df, y=\"y\", g=\"first_treat_year\", t=\"year\", i=\"firm_id\")   # CS 2021\nsp.sun_abraham(df, y=\"y\", g=\"first_treat_year\", t=\"year\", i=\"firm_id\")         # SA 2021 event study\nsp.bacon_decomposition(df, y=\"y\", treat=\"treated\", time=\"year\", id=\"firm_id\")  # TWFE diagnostic\n\nsp.honest_did(result, method=\"smoothness\")                                     # PT sensitivity (RR 2023)\nsp.continuous_did(df, y=\"y\", dose=\"dose\", time=\"year\", id=\"firm_id\")           # Continuous treatment\n```\n\n### Regression Discontinuity\n```python\n# Cutoff argument is `c=` (not `cutoff=`) across rdrobust / rkd.\nsp.rdrobust(df, y=\"y\", x=\"running_var\", c=0)                       # Sharp RD (CCT 2014)\nsp.rdrobust(df, y=\"y\", x=\"running_var\", c=0, fuzzy=\"treatment\")    # Fuzzy RD\nsp.rddensity(df, x=\"running_var\", c=0)                             # McCrary density test\nsp.rdmc(df, y=\"y\", x=\"running_var\", cutoffs=[0, 5, 10])            # Multi-cutoff RD\nsp.rkd(df, y=\"y\", x=\"running_var\", c=0)                            # Regression kink design\n```\n\n### Matching & Reweighting\n```python\n# Signature is (data, y, treat, covariates, ...) — outcome comes BEFORE treat.\nsp.match(df, y=\"wage\", treat=\"training\", covariates=[\"age\", \"edu\"], method=\"nearest\")   # PSM (method='nearest' is default)\nsp.match(df, y=\"wage\", treat=\"training\", covariates=[\"age\", \"edu\"], method=\"cem\")       # Coarsened exact matching\nsp.ebalance(df, y=\"wage\", treat=\"training\", covariates=[\"age\", \"edu\"])                  # Entropy balancing\n```\n\n### Synthetic Control\n```python\n# Kwarg is treatment_time (NOT treated_period); treated_unit / treatment_time are singular.\nsp.synth(df, outcome=\"y\", unit=\"unit\", time=\"time\",\n         treated_unit=1, treatment_time=2000)                        # ADH SCM (method='augmented' default)\nsp.sdid(df, outcome=\"y\", unit=\"unit\", time=\"time\",\n        treated_unit=1, treatment_time=2000)                         # Synthetic DID (Arkhangelsky et al. 2021)\n```\n\n### Machine Learning Causal Inference\n```python\nsp.dml(df, y=\"wage\", treat=\"training\", covariates=[\"age\", \"edu\"], model=\"plr\")     # Double/Debiased ML\nsp.causal_forest(formula=\"wage ~ training | age + edu\", data=df)                    # Causal Forest (GRF) — formula API\nsp.metalearner(df, y=\"wage\", treat=\"training\", covariates=[\"age\", \"edu\"], learner=\"dr\")  # DR-Learner\nsp.tmle(df, y=\"wage\", treat=\"training\", covariates=[\"age\", \"edu\"])                 # Targeted MLE\nsp.aipw(df, y=\"wage\", treat=\"training\", covariates=[\"age\", \"edu\"])                 # Augmented IPW\n```\n\n### Neural Causal Models\n```python\nsp.tarnet(df, y=\"wage\", treat=\"training\", covariates=[\"age\", \"edu\"])       # TARNet\nsp.cfrnet(df, y=\"wage\", treat=\"training\", covariates=[\"age\", \"edu\"])       # CFRNet\nsp.dragonnet(df, y=\"wage\", treat=\"training\", covariates=[\"age\", \"edu\"])    # DragonNet\n```\n\n### Text Causal (v1.6 P1, experimental)\n```python\n# text_treatment_effect: pass the TEXT COLUMN name (text_col=), not pre-computed embeddings.\n# The `embedder=` argument controls how text is vectorised ('hash' default, or a callable).\nsp.causal_text.text_treatment_effect(                      # Veitch–Wang–Blei (2020) text-as-treatment\n    df, text_col=\"doc\", outcome=\"y\", treatment=\"t\",\n    covariates=[\"age\", \"edu\"], embedder=\"hash\", n_components=20)\n\n# llm_annotator_correct: takes aligned pd.Series (NOT a DataFrame).\n# annotations_human must be same length as annotations_llm — mark unlabelled rows with NaN\n# if you only have human labels on a validation subset.\nsp.causal_text.llm_annotator_correct(                      # Egami–Hinck–Stewart–Wei (2024)\n    annotations_llm=df[\"t_llm\"],                           #   LLM-annotated treatment (all rows)\n    annotations_human=df[\"t_true\"],                        #   human labels aligned; NaN where missing\n    outcome=df[\"y\"],\n    covariates=df[[\"age\", \"edu\"]],\n    method=\"hausman\")\n```\n\n### Robustness & Workflow\n```python\n# spec_curve: controls is List[List[str]] (each inner list = one spec), not a flat list.\nsp.spec_curve(df, y=\"wage\", x=\"training\",\n              controls=[[\"age\"], [\"age\", \"edu\"], [\"age\", \"edu\", \"tenure\"]])\n\n# robustness_report: takes (data, formula, x, ...) — NOT a result object.\nsp.robustness_report(df, formula=\"wage ~ training + age + edu\",\n                     x=\"training\", cluster_var=\"firm_id\")\n\n# subgroup_analysis: (data, formula, x, by={<label>: <col>}, ...). Wald test is automatic.\nsp.subgroup_analysis(df, formula=\"wage ~ training + age + edu\",\n                     x=\"training\", by={\"gender\": \"female\", \"age_bin\": \"age_quartile\"})\n\nresult.to_latex()                                          # Export to LaTeX\nresult.to_word(\"output.docx\")                              # Export to Word\nresult.cite()                                              # Auto-generate citation\n```\n\n### Interactive Visualization (v0.6+)\n```python\nfig = result.plot()\nsp.interactive(fig)  # Stata Graph Editor-style WYSIWYG editing, 29 academic themes\n```\n\n## Agent Integration Pattern\n\n```python\nimport statspai as sp\n\n# Step 1: Discover available functions\nfunctions = sp.list_functions()\n\n# Step 2: Understand a specific function\ninfo = sp.describe_function(\"callaway_santanna\")\n\n# Step 3: Get JSON schema for structured calls\nschema = sp.function_schema(\"callaway_santanna\")\n\n# Step 4: Execute and get structured results (callaway_santanna requires `i=` unit id)\nresult = sp.callaway_santanna(df, y=\"y\", g=\"first_treat_year\", t=\"year\", i=\"firm_id\")\nprint(result.summary())\nresult.to_latex(\"tables/did_results.tex\")\n```\n\n## When to Use StatsPAI vs Other Packages\n\n| Scenario | Use StatsPAI | Alternative |\n|----------|-------------|-------------|\n| One-stop empirical pipeline (EDA → estimand → DAG → estimate → robustness) | ✅ Single import covers all six steps | Assemble 10+ R/Python packages |\n| Agent-driven analysis with self-describing API | ✅ `list_functions` / `describe_function` / `function_schema` | pyfixest, statsmodels (no agent API) |\n| \"DID vs RD vs IV?\" decision (estimand-first) | ✅ `sp.causal_question` + `sp.causal` recommender | None — usually a manual judgement call |\n| LLM-assisted DAG discovery loop | ✅ `sp.llm_dag_propose / validate / constrained` | causal-learn (no LLM oracle integration) |\n| Staggered DID with diagnostics | ✅ CS + SA + Bacon + HonestDID in one place | differences (partial) |\n| Neural causal models | ✅ TARNet / CFRNet / DragonNet | econml (partial) |\n| Stata users migrating to Python | ✅ Stata-equivalent names (`sp.regress`, `sp.estat`, `sp.sumstats`) | linearmodels (limited) |\n\n## Validation and Error Handling\n\nAfter running any estimation, check the result object before proceeding:\n\n```python\nresult = sp.did(df, \"y\", \"treated\", \"post\")\n\n# Always inspect the human-readable summary first\nprint(result.summary())\n\n# Inspect structured diagnostics for agent-driven logic\nif hasattr(result, \"diagnostics\"):\n    print(result.diagnostics)\n```\n\nCommon pitfalls to guard against:\n\n- **Convergence warnings** — surfaced in `result.summary()` (check before trusting SEs).\n- **Weak instruments** for IV — require first-stage F ≥ 10 (Stock–Yogo rule of thumb); StatsPAI exposes this in `result.diagnostics[\"First-stage F (<endog>)\"]`.\n- **Parallel trends** for DID — run an event study and verify pre-treatment coefficients are statistically indistinguishable from zero; follow up with `sp.honest_did(result)` for Rambachan–Roth sensitivity.\n- **Bandwidth sensitivity** for RDD — re-run `sp.rdrobust` at half and double the MSE-optimal bandwidth; agreement within one SE is reassuring.\n- **Missing data** — StatsPAI drops rows with missing values by default; check `result.data_info[\"n_obs\"]` matches your expected sample size.\n- **Overlap / common support** — for matching, DML, and meta-learners, inspect propensity-score distributions before interpreting CATEs.","tags":["brycewang","stanford","statspai","awesome","agent","skills","for","empirical","research","brycewang-stanford","academic-research","agent-skills"],"capabilities":["skill","source-brycewang-stanford","skill-00-brycewang-stanford-statspai","topic-academic-research","topic-agent-skills","topic-ai-agent","topic-awesome-list","topic-communication","topic-copaper","topic-economics","topic-education","topic-empirical-research","topic-international-relations","topic-political-science","topic-psychology"],"categories":["Awesome-Agent-Skills-for-Empirical-Research"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/brycewang-stanford/Awesome-Agent-Skills-for-Empirical-Research/00-brycewang-stanford-StatsPAI","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add brycewang-stanford/Awesome-Agent-Skills-for-Empirical-Research","source_repo":"https://github.com/brycewang-stanford/Awesome-Agent-Skills-for-Empirical-Research","install_from":"skills.sh"}},"qualityScore":"0.581","qualityRationale":"deterministic score 0.58 from registry signals: · indexed on github topic:agent-skills · 263 github stars · SKILL.md body (16,909 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-23T18:55:16.146Z","embedding":null,"createdAt":"2026-04-18T22:12:40.736Z","updatedAt":"2026-04-23T18:55:16.146Z","lastSeenAt":"2026-04-23T18:55:16.146Z","tsv":"'/brycewang-stanford/statspai':82 '0':232,332,475,1289,1302,1313,1325,1340 '0.05':818 '0.5':1160 '0/1':849 '1':117,242,468,499,531,1424,1443,1815 '10':1327,1907,2070 '2':138,250,533,1174,1823 '20':1615 '2000':1427,1446 '2010':709 '2014':1293 '2020':710,1595 '2021':1213,1229,1452 '2023':1254 '2024':1656 '29':1803 '2x2':1168 '3':165,261,637,864,1834 '390':20,71 '4':186,268,755,1847 '5':281,631,879,1326 '6':287,316,333,948 'abraham':1215 'academ':1804 'across':1278 'actual':371 'adh':1428 'adopt':589 'age':350,525,612,730,910,1032,1033,1035,1135,1364,1380,1394,1465,1476,1492,1506,1517,1532,1542,1552,1609,1684,1715,1716,1718,1737,1761,1768,1770 'agent':3,47,56,101,130,163,224,367,472,893,1806,1911,1928,2038 'agent-driven':1910,2037 'agent-n':2,46,55 'agreement':2131 'al':1451 'align':1620,1675 'alpha':817 'altern':1889 'alway':2023 'analysi':15,407,1746,1756,1913 'analysis-readi':406 'annot':1617,1625,1632,1650,1657,1664,1668 'api':29,121,1484,1918,1929 'appli':64 'argument':389,1273,1578 'arkhangelski':1449 'arriv':403 'assembl':1906 'assist':761,1951 'assum':401 'assumpt':673,737 'att':712 'augment':1431,1519 'auto':714,1785 'auto-gener':1784 'autom':934 'automat':626,1754 'avail':1817 'back':321,856 'backend':770 'bacon':1973 'balanc':546,553,555,566,575,1397 'bandwidth':2114,2130 'batteri':936,961 'behind':184 'bin':1769 'blei':1594 'block':328 'boundari':394 'bug':492 'built':110 'c':1275,1288,1301,1312,1339 'call':419,883,890,938,1840,1948 'callabl':1588 'callaway':1831,1844,1853 'canon':223 'catalog':945,1077 'catch':538 'cate':2174 'causal':49,61,1455,1480,1522,1556,1961,1981 'causal-learn':1960 'causalresult':146,320 'cct':1292 'cem':1383 'cfrnet':1544,1984 'check':254,537,2010,2057,2147 'choic':202 'ci':806,833,930,982,998 'ci-valid':832 'citat':1787 'cite':156 'classic':1078 'clean':36,234 'client':790,793 'clip':466 'close':763 'cluster':1096,1107,1741 'coarsen':1384 'code':327 'coeffici':2098 'coerc':448 'coercion':450 'cohort':595 'col':1570,1602 'column':357,372,1196,1567 'come':1354 'commit':676 'common':2047,2158 'complet':32,75,797 'compon':1614 'comput':1574 'conf':992 'confound':1008 'constrain':279,828,831,841,1959 'continu':1267 'control':1012,1031,1399,1579,1693,1714 'converg':2052 'correct':1618,1651 'covari':453,524,597,729,909,1352,1363,1379,1393,1464,1491,1505,1516,1531,1541,1551,1608,1682 'cover':30,73,168,1902 'cs':1212,1971 'csv':430 'curv':292,684,1011,1025,1692,1708 'cutoff':1272,1277,1324,1330 'dag':178,272,275,278,762,773,780,813,840,868,871,913,1897,1952,1956 'data':14,35,233,479,704,810,826,1087,1349,1478,1724,1747,2138 'data-analysi':13 'datafram':379,409,1624 'dataset':228 'decid':580 'decis':190,649,681,1935 'declar':658 'decomposit':1047,1233 'default':1372,1432,1585,2146 'defens':205 'demot':835 'densiti':1315 'describ':120,1917,1921 'descript':37,172,244,500,843 'design':363,374,539,663,713,907,1343 'df':428,432,441,445,451,460,464,505,515,521,558,568,573,608,705,816,842,897,1026,1042,1048,1095,1106,1115,1131,1154,1181,1200,1216,1234,1257,1282,1295,1308,1318,1333,1358,1374,1388,1415,1434,1459,1479,1486,1500,1511,1526,1536,1546,1600,1659,1670,1680,1683,1709,1733,1757,1862,2019 'df.columns.tolist':783 'df.dropna':433 'df.groupby':590 'df.merge':452 'diagnost':160,181,288,619,949,1059,1245,1970,2035,2044 'dict':161,604 'differ':1164,1166,1978 'difference-in-differ':1163 'direct':942 'dirti':478 'discontinu':1270 'discov':131,838,1816 'discovered.dag':872,914 'discoveri':179,829,1953 'distribut':2171 'dml':2162 'doc':136,1603 'domain':777,784 'dose':1260,1261 'doubl':2125 'double/debiased':1469 'dr':1495,1497 'dr-learner':1496 'draft':303,771 'dragonnet':1554,1985 'driven':114,1912,2039 'drop':488,548,571,581,2140 'dsl':177,657 'duplic':634 'e':977 'e-valu':976 'econml':1986 'econom':339,786 'econometr':51,65,106,1079 'eda':39,243,502,601,1895 'edg':805,824,853 'edit':1802 'editor':1799 'editor-styl':1798 'edu':351,508,526,613,731,911,1034,1036,1136,1365,1381,1395,1466,1477,1493,1507,1518,1533,1543,1553,1610,1685,1717,1719,1738,1762 'effect':1563,1591 'egami':1652 'either':484 'embed':1575 'embedd':1577,1611 'empir':12,76,115,213,1893 'end':210,212,300,302 'end-to-end':209,299 'endog':1111 'entiti':559,1119 'entropi':1396 'eq':1044 'equival':1995 'error':447,485,2004 'estim':143,180,282,482,542,668,736,751,880,887,923,928,941,981,995,1190,1898,2009 'estimand':188,361,639,655,662,711,1896,1937 'estimand-first':187,638,654,1936 'et':1450 'etl':417 'event':1230,2091 'everi':142,356 'evid':821 'exact':1173,1385 'exampl':334 'excel':155 'execut':1848 'exist':297 'exog':1113 'exp':509 'expect':2154 'experiment':1559 'explicit':203 'explor':270,757 'export':1774,1780 'expos':2077 'extract':989 'f':570,2069,2084 'failur':540 'fall':855 'fallback':738 'fe':1124,1126 'feed':477 'femal':1767 'fig':1792,1795 'find':933 'firm':347,455,560,1097,1120,1210,1226,1242,1265,1743,1872 'first':105,189,591,640,656,1085,1204,1220,1866,1938,2030,2067,2082 'first-stag':2066,2081 'fit':964 'flat':1705 'flight':253,536 'flow':221 'follow':2104 'forc':1142 'forest':1472,1481 'formula':1084,1155,1473,1483,1725,1734,1748,1758 'full':11,170,615 'function':21,72,123,125,134,386,422,1818,1819,1821,1827,1830,1920,1922,1923 'fuzzi':1303,1305 'g':1203,1219,1865 'gender':1766 'generat':304,1786 'generic':600 'get':1835,1850 'github.com':81 'github.com/brycewang-stanford/statspai':80 'graph':1797 'grf':1482 'guard':2050 'guess':208 'half':2123 'hand':318 'handl':2005 'hasattr':2042 'hash':1584,1612 'hausman':1687 'heckman':1137 'heurist':769,801 'hinck':1653 'honestdid':1974 'human':742,1626,1643,1669,1673,2027 'human-read':741,2026 'id':346,348,456,561,726,728,902,904,1055,1057,1098,1195,1211,1227,1241,1243,1264,1266,1744,1858,1873 'identif':617,874,918 'identifi':266,665 'identification-level':616 'identificationplan':735 'illustr':366 'import':23,24,67,167,424,1810,1901 'incom':527 'indic':1178 'indistinguish':2101 'industri':1043 'infer':50,62,1456 'info':1828,2149 'inner':1020,1699 'insid':627 'inspect':2024,2033,2167 'instal':85 'instrument':1112,2062 'int':993,1001 'integr':1807,1966 'interact':1788 'interpret':2173 'ipw':1520 'iter':863 'iv':201,622,648,718,958,1934,2064 'iv/2sls':1109 'ivreg':1082 'join':459 'joss':95 'journal':90 'json':1836 'judgement':1947 'keep':583 'key':439 'kid':1145 'kink':1342 'kwarg':1127,1401 'label':517,1644,1674 'labor':338,785,1141 'labor-econom':337 'latex':151,1773,1776,1877 'layer':682,689 'learn':1454,1962 'learner':1494,1498,2166 'left':458 'len':565,567,572,574 'length':1630 'level':618 'leverag':624,960 'limit':2001 'linearmodel':2000 'list':1016,1018,1021,1695,1696,1700,1706,1919 'llm':113,760,767,792,1616,1633,1658,1661,1663,1950,1964 'llm-annot':1662 'llm-assist':759,1949 'llm-driven':112 'load':230 'loc':1002 'log':461 'logic':164,2040 'lookup':137 'loop':33,225,764,1954 'lower':467 'machin':1453 'make':195 'manual':1946 'manuf':1041 'manufactur':707,1045 'marit':1144 'mark':1634 'match':1344,1386,2152,2161 'max':862 'mccrari':1314 'measur':1004 'meta':2165 'meta-learn':2164 'method':744,944,969,1076,1123,1129,1249,1366,1369,1382,1430,1686 'migrat':1990 'miss':259,437,1678,2137,2143 'ml':1470 'mle':1509 'model':269,756,1467,1523,1982 'month':845 'mse':2128 'mse-optim':2127 'multi':1329 'multi-cutoff':1328 'multivers':690 'must':368,1013,1171,1627 'my_llm_client.suggest':852 'n':1613,2150 'name':358,387,776,1073,1568,1996 'nan':1638,1676 'narrat':341 'nativ':4,48,57 'nearest':1367,1370 'neural':1521,1980 'none':800,1040,1943 'normat':392 'note':325 'np.log':463 'numer':444 'ob':720,2151 'object':141,795,988,1730,2013 'ol':1099 'one':6,22,66,166,219,336,882,889,1022,1701,1891,1976,2133 'one-cal':881,888 'one-stop':5,218,1890 'open':92 'optim':2129 'option':854,915 'oracl':851,1965 'orchestr':884 'outcom':598,661,702,1148,1353,1416,1435,1604,1679 'output':512 'output.docx':1779 'overlap':258,623,959,2157 'p1':216,1558 'packag':59,1885,1909 'panda':235,413,425 'pane':44 'panel':256,544,547,554,557,723,1125 'paper':87 'paragraph':745 'parallel':2085 'param':991 'partial':1979,1987 'pass':865,1564 'pattern':1808 'pc':859 'pd':427 'pd.read':429 'pd.series':1621 'pd.to':443 'per':804 'per-edg':803 'period':1407 'pick':666,750 'pip':84 'pipelin':16,171,214,1894 'pitfal':2048 'place':1977 'plain':858 'plan':733,740 'plot':149 'plr':1468 'point':927,980 'popul':359,659,706 'post':1177,1187,2022 'postestim':1070 'pre':252,535,1573,2096 'pre-comput':1572 'pre-flight':251,534 'pre-treat':2095 'prefer':416 'print':569,739,752,819,916,920,925,931,1874,2031,2045 'proceed':2015 'program':850 'prompt':798 'propens':2169 'propensity-scor':2168 'propos':273,766,778,781,815,823,830,1957 'psm':1368 'pt':620,955,973,1251 'pure':353 'purpos':109 'purpose-built':108 'pyfixest':1925 'pypi':83 'python':18,58,423,503,543,696,765,894,951,1080,1167,1271,1346,1400,1457,1524,1560,1690,1791,1809,1992,2016 'q':697 'q.estimate':747 'q.identify':734 'quantil':1159,1161 'quartil':1771 'question':176,192,263,265,382,642,651,699,1940 'r/python':1908 'rambachan':971,2111 'raw.csv':431 'rct':719 'rd':199,646,1291,1306,1331,1932 'rdd':717,2117 'rdrobust':129,1279 're':675,2119 're-run':2118 'readabl':355,743,2028 'readi':408 'reason':875 'reassur':2136 'recommend':891,1942 'regress':1081,1162,1269,1341 'report':605,606,1722,1732 'requir':1191,1855,2065 'research':77,116,175,262,381,641 'research-quest':174 'result':140,688,746,867,953,954,965,968,987,1064,1248,1729,1852,1859,2012,2017,2043,2109 'result.cite':1783 'result.conf':1000 'result.data':2148 'result.diagnostics':2046,2080 'result.params':996 'result.plot':1793 'result.summary':753,1875,2032,2056 'result.to':1772,1777,1876 'results-lay':687 'return':144,551,602 'review':97 'reweight':1345 'rkd':1280 'robust':182,289,935,950,1688,1721,1899 'roth':972,2112 'row':489,576,1636,1667,2141 'rr':1005,1253 'rule':2073 'run':340,625,748,1286,1299,1310,1322,1337,2007,2089,2120 'sa':1228,1972 'sampl':2155 'saniti':599 'santanna':1199,1832,1845,1854,1861 'scenario':1886 'schema':128,1837,1841,1843,1924 'scm':1429 'scope':239,309,393 'score':2170 'se':929,984,2134 'see':238,943 'select':1138,1139,1149,1152 'self':119,1916 'self-describ':118,1915 'sensit':974,1009,1252,2113,2115 'ses':2060 'shape':390 'share':335 'sharp':1290 'signatur':1347 'silent':487 'singl':1071,1900 'singular':1413 'six':1904 'size':594,596,2156 'skill':312 'skill-00-brycewang-stanford-statspai' 'skip':473 'smooth':970,1250 'softwar':94 'sourc':79,93 'source-brycewang-stanford' 'sp':27,70,185,285,385,421,481,1813 'sp.aipw':1510 'sp.bacon':1046,1232 'sp.balance':41,43,246,255,519,556 'sp.callaway':1198,1860 'sp.causal':191,194,264,283,628,650,698,870,896,1471,1939,1941 'sp.causal_text.llm':1649 'sp.causal_text.text':1589 'sp.cfrnet':1535 'sp.continuous':1255 'sp.describe':124,248,514,1829 'sp.diagnose':257,290,607,952 'sp.did':1180,2018 'sp.dml':1458 'sp.dragonnet':1545 'sp.ebalance':1387 'sp.estat':1063,1998 'sp.evalue':295,994 'sp.function':127,1842 'sp.heckman':1130 'sp.honest':293,966,1246,2107 'sp.interactive':1794 'sp.ivreg':1100 'sp.list':122,1820 'sp.llm':271,274,277,779,812,839,1955 'sp.match':1357,1373 'sp.metalearner':1485 'sp.panel':1114 'sp.paper':296 'sp.qreg':1153 'sp.rddensity':1307 'sp.rdmc':1317 'sp.rdrobust':1281,1294,2121 'sp.regress':1091,1997 'sp.rkd':1332 'sp.robustness':1731 'sp.sdid':1433 'sp.spec':291,683,1024,1707 'sp.subgroup':1755 'sp.sumstats':40,245,504,1999 'sp.sun':1214 'sp.synth':1414 'sp.tarnet':1525 'sp.tmle':1499 'spec':1023,1691,1702 'specif':886,940,1010,1826 'stabl':837 'stage':2068,2083 'stagger':588,1061,1188,1967 'stat':38,173 'stata':1068,1796,1988,1994 'stata-equival':1993 'stata-styl':1067 'state':1108 'statist':501,2100 'statsmodel':1089,1926 'statsmodels-styl':1088 'statspai':1,25,45,52,68,86,99,102,237,396,400,496,1811,1882,1888,2076,2139 'step':231,241,249,260,267,280,286,315,331,474,498,532,630,636,754,878,947,1814,1822,1833,1846,1905 'stewart':1654 'stock':2071 'stop':7,220,313,1892 'str':799,1697 'string':360 'structur':159,545,722,1839,1851,2034 'studi':1231,2092 'style':1069,1090,1800 'subgroup':1745 'submit':88 'subset':434,1038,1648 'substitut':369,695 'summari':148,2029 'support':827,2159 'surfac':2054 'syntax':1110 'synthet':1398,1447 'tabl':42,247,520,530 'table1.docx':513 'tables/did_results.tex':1878 'take':979,1083,1172,1619,1723 'target':1508 'tarnet':1534,1983 'tenur':352,614,732,789,912,1037,1720 'test':528,807,1065,1072,1316,1752 'text':1555,1561,1566,1569,1581,1597,1601 'text-as-treat':1596 'theme':1805 'thumb':2075 'time':562,587,721,724,905,1053,1121,1170,1186,1239,1262,1404,1411,1420,1421,1426,1439,1440,1445 'toolkit':8,107 'topic-academic-research' 'topic-agent-skills' 'topic-ai-agent' 'topic-awesome-list' 'topic-communication' 'topic-copaper' 'topic-economics' 'topic-education' 'topic-empirical-research' 'topic-international-relations' 'topic-political-science' 'topic-psychology' 'train':342,701,787,848,901,997,1003,1030,1052,1362,1378,1392,1463,1475,1490,1504,1515,1530,1540,1550,1713,1736,1740,1760,1764 'transform':469 'treat':511,522,523,592,1051,1184,1185,1205,1221,1237,1238,1351,1356,1361,1377,1391,1406,1408,1422,1441,1462,1489,1503,1514,1529,1539,1549,1867,2021 'treatment':436,586,660,700,900,1268,1304,1403,1410,1425,1444,1562,1590,1599,1606,1665,2097 'trend':2086 'true':1672 'trust':2059 'ttest':529 'tupl':999 'twfe':1058,1244 'type':449,518 'unbalanc':549,578 'understand':133,1824 'unifi':28,139 'unit':550,579,1194,1409,1418,1419,1423,1437,1438,1442,1857 'unit-id':1193 'unlabel':1635 'unmeasur':1007 'unmeasured-confound':1006 'usd':847 'use':876,1881,1887 'user':324,377,1989 'usual':1944 'v0.6':1790 'v1.6':19,215,1557 'valid':276,802,811,814,834,1647,1958,2002 'validation.edge':820 'valu':364,978,1175,2144 'var':440,506,1287,1300,1311,1323,1338,1742 'variabl':516,775,782 'vectoris':1583 'veitch':1592 'verdict':919 'verifi':2094 'via':758 'visual':1789 'vs':198,200,582,645,647,1883,1931,1933 'w':895 'w.diagnostics':917 'w.recommendation':921 'w.result.summary':926 'w.robustness':932 'wage':343,462,465,507,610,703,788,844,846,899,1028,1050,1133,1360,1376,1390,1461,1474,1488,1502,1513,1528,1538,1548,1711,1735,1759 'wald':1751 'wang':1593 'warn':2053 'weak':621,957,2061 'weak-iv':956 'wei':1655 'within':2132 'without':135,860 'word':153,1778,1782 'work':1179 'worker':345,708,727,903,1056 'workflow':78,1689 'write':670 'wysiwyg':1801 'x':611,1029,1134,1285,1298,1309,1321,1336,1712,1726,1739,1749,1763 'x1':1093,1102,1117,1157 'x2':1094,1105,1118,1158 'y':435,609,898,1027,1049,1092,1101,1116,1132,1156,1182,1183,1201,1202,1217,1218,1235,1236,1258,1259,1283,1284,1296,1297,1319,1320,1334,1335,1350,1359,1375,1389,1417,1436,1460,1487,1501,1512,1527,1537,1547,1605,1681,1710,1863,1864,2020 'y/x':1146 'year':349,442,446,563,593,725,906,1054,1122,1206,1208,1222,1224,1240,1263,1868,1870 'yogo':2072 'z':1143,1150 'z1':1103 'z2':1104 'zero':2103","prices":[{"id":"15a592c7-f1c7-4716-aac3-81ada809116e","listingId":"490bc560-f3fe-456f-9b9a-92db2c849799","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"brycewang-stanford","category":"Awesome-Agent-Skills-for-Empirical-Research","install_from":"skills.sh"},"createdAt":"2026-04-18T22:12:40.736Z"}],"sources":[{"listingId":"490bc560-f3fe-456f-9b9a-92db2c849799","source":"github","sourceId":"brycewang-stanford/Awesome-Agent-Skills-for-Empirical-Research/00-brycewang-stanford-StatsPAI","sourceUrl":"https://github.com/brycewang-stanford/Awesome-Agent-Skills-for-Empirical-Research/tree/main/skills/00-brycewang-stanford-StatsPAI","isPrimary":false,"firstSeenAt":"2026-04-18T22:12:40.736Z","lastSeenAt":"2026-04-23T18:55:16.146Z"}],"details":{"listingId":"490bc560-f3fe-456f-9b9a-92db2c849799","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"brycewang-stanford","slug":"00-brycewang-stanford-StatsPAI","github":{"repo":"brycewang-stanford/Awesome-Agent-Skills-for-Empirical-Research","stars":263,"topics":["academic-research","agent-skills","ai-agent","awesome-list","communication","copaper","economics","education","empirical-research","international-relations","political-science","psychology","public-administration","reproducible-research","skills-library","social-science","sociology"],"license":"other","html_url":"https://github.com/brycewang-stanford/Awesome-Agent-Skills-for-Empirical-Research","pushed_at":"2026-04-23T08:11:44Z","description":"🔬 A curated collection of 23,000+ agent skills for empirical research across 8 social science disciplines. | 精选 23,000+ AI Agent 技能库，覆盖8大社会科学学科的实证研究。CoPaper.AI 20分钟完成一篇可复现的规范实证论文，并支持用户上传 Skills。-- Maintained by CoPaper.AI from Stanford REAP.","skill_md_sha":"23a487b8f3b2b704f35b879ec9eaa42c50e9d4ae","skill_md_path":"skills/00-brycewang-stanford-StatsPAI/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/brycewang-stanford/Awesome-Agent-Skills-for-Empirical-Research/tree/main/skills/00-brycewang-stanford-StatsPAI"},"layout":"multi","source":"github","category":"Awesome-Agent-Skills-for-Empirical-Research","frontmatter":{"name":"statspai","description":"Agent-native one-stop toolkit for the full empirical data-analysis pipeline in Python (v1.6+). 390+ functions, one import (`import statspai as sp`), unified API. Covers the complete loop after data cleaning — descriptive stats & EDA (sp.sumstats, sp.balance_table, sp.balance_panel), estimand-first research-question DSL (sp.causal_question), LLM-assisted DAG discovery (sp.llm_dag_propose/validate/constrained), one-call orchestration (sp.causal), classical estimators (OLS, IV, DID, staggered DID, RDD, PSM, SCM), ML causal (DML, Causal Forest, Meta-Learners, TMLE), neural causal, text causal (sp.causal_text), and diagnostics + robustness (sp.diagnose, sp.spec_curve, sp.honest_did). Use when the user asks to run a full empirical analysis, decide which estimator to use (\"DID vs RD vs IV?\"), explore models via DAG, estimate treatment effects, evaluate policy, run observational studies, or apply any of the listed econometric methods in Python. Every function returns structured result objects with self-describing schemas for LLM-driven workflows. Data cleaning (missing values, type coercion, merges) is *not* covered — handle that with pandas first, then enter StatsPAI."},"skills_sh_url":"https://skills.sh/brycewang-stanford/Awesome-Agent-Skills-for-Empirical-Research/00-brycewang-stanford-StatsPAI"},"updatedAt":"2026-04-23T18:55:16.146Z"}}