Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
2b1e76b
Add BusinessReport and DiagnosticReport for practitioner-ready output
igerber Apr 18, 2026
3212187
Address review findings: Wald-path tests, outcome_direction, warning …
igerber Apr 18, 2026
7502676
Tighten README: frame BR/DR as experimental preview
igerber Apr 18, 2026
2577d6c
Address CI review findings on PR #318
igerber Apr 18, 2026
989f71a
Address second round of CI review findings on PR #318
igerber Apr 18, 2026
959f84e
Address third round of CI review findings on PR #318
igerber Apr 18, 2026
345f65c
Address fourth round of CI review findings on PR #318
igerber Apr 18, 2026
311a7be
Address fifth round of CI review findings on PR #318
igerber Apr 18, 2026
df2636b
Address sixth round of CI review findings on PR #318
igerber Apr 18, 2026
d8fa66d
Address seventh round of CI review findings on PR #318
igerber Apr 18, 2026
7b5c0ad
Address eighth round of CI review findings on PR #318
igerber Apr 18, 2026
ed6f220
Address ninth round of CI review findings on PR #318
igerber Apr 18, 2026
6283476
Merge remote-tracking branch 'origin/main' into business-report
igerber Apr 18, 2026
25cb886
Address tenth round of CI review findings on PR #318
igerber Apr 18, 2026
4bb7dcd
Address eleventh round of CI review findings on PR #318
igerber Apr 19, 2026
5ee5d37
Address twelfth round of CI review findings on PR #318
igerber Apr 19, 2026
6bdae48
Address thirteenth round of CI review findings on PR #318
igerber Apr 19, 2026
9a93be3
Address fourteenth round of CI review findings on PR #318
igerber Apr 19, 2026
60122a9
Address fifteenth round of CI review findings on PR #318
igerber Apr 19, 2026
ead5d2a
Address sixteenth round of CI review findings on PR #318
igerber Apr 19, 2026
ac7cbf2
Address seventeenth round of CI review findings on PR #318
igerber Apr 19, 2026
d8a49c7
Address eighteenth round of CI review findings on PR #318
igerber Apr 19, 2026
dba9107
Address nineteenth round of CI review findings on PR #318
igerber Apr 19, 2026
124b1bf
Address twentieth round of CI review findings on PR #318
igerber Apr 19, 2026
d26e02b
Address twenty-first round of CI review findings on PR #318
igerber Apr 19, 2026
722400d
Address twenty-second round of CI review findings on PR #318
igerber Apr 19, 2026
61270b8
Address twenty-third round of CI review findings on PR #318
igerber Apr 19, 2026
dae62ac
Address twenty-fourth round of CI review findings on PR #318
igerber Apr 19, 2026
3167f05
Address twenty-fifth round of CI review findings on PR #318
igerber Apr 19, 2026
d9b16cb
Address twenty-sixth round of CI review findings on PR #318
igerber Apr 19, 2026
e3f9bfe
Address twenty-seventh round of CI review findings on PR #318
igerber Apr 19, 2026
cd85eda
Address twenty-eighth round of CI review findings on PR #318
igerber Apr 19, 2026
59d7df7
Address twenty-ninth round of CI review findings on PR #318
igerber Apr 19, 2026
c6d672e
Address thirtieth round of CI review findings on PR #318
igerber Apr 19, 2026
95c4a7a
Address thirty-first round of CI review findings on PR #318
igerber Apr 19, 2026
c8d9d84
Address thirty-second round of CI review findings on PR #318
igerber Apr 19, 2026
9cbe425
Address thirty-third round of CI review findings on PR #318
igerber Apr 19, 2026
94e9110
Address thirty-fourth round of CI review findings on PR #318
igerber Apr 19, 2026
7743b5c
Address thirty-fifth round of CI review findings on PR #318
igerber Apr 19, 2026
6b251af
Address thirty-sixth round of CI review findings on PR #318
igerber Apr 19, 2026
8838303
Address thirty-seventh round of CI review findings on PR #318
igerber Apr 19, 2026
86c4a5a
Address thirty-eighth round of CI review findings on PR #318
igerber Apr 19, 2026
9d8ad34
Address thirty-ninth round of CI review findings on PR #318
igerber Apr 19, 2026
cf2f592
Address fortieth round of CI review findings on PR #318
igerber Apr 19, 2026
020d537
Address forty-first round of CI review findings on PR #318
igerber Apr 19, 2026
5788e26
Address forty-second round of CI review findings on PR #318
igerber Apr 19, 2026
e2115bc
Address forty-third round of CI review findings on PR #318
igerber Apr 19, 2026
1085e72
Address forty-fourth round of CI review findings on PR #318
igerber Apr 19, 2026
dcfb4fe
Address forty-fifth round of CI review findings on PR #318
igerber Apr 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- **`BusinessReport` and `DiagnosticReport` (experimental preview)** - practitioner-ready output layer. `BusinessReport(results, ...)` produces plain-English narrative summaries (`.summary()`, `.full_report()`, `.export_markdown()`, `.to_dict()`) from any of the 16 fitted result types. `DiagnosticReport(results, ...)` orchestrates the existing diagnostic battery (parallel trends, pre-trends power, HonestDiD sensitivity, Goodman-Bacon, heterogeneity, design-effect, EPV) plus estimator-native diagnostics for SyntheticDiD (`pre_treatment_fit`, weight concentration, in-time placebo, zeta sensitivity) and TROP (factor-model fit metrics). Both classes expose an AI-legible `to_dict()` schema (single source of truth; prose renders from the dict). BR auto-constructs DR by default so summaries mention pre-trends, robustness, and design-effect findings in one call. See `docs/methodology/REPORTING.md` for methodology deviations including the no-traffic-light-gates decision, pre-trends verdict thresholds (0.05 / 0.30), and power-aware phrasing driven by `compute_pretrends_power`. **Both schemas are marked experimental in this release** - wording, verdict thresholds, and schema shape will change; do not anchor downstream tooling on them yet.

### Changed
- Add Zenodo DOI badge to README; upgrade the BibTeX citation block with the concept DOI (`10.5281/zenodo.19646175`) and list author as Isaac Gerber (matching `CITATION.cff`). Add `doi:` and `identifiers:` entries (concept + versioned) to `CITATION.cff`. DOI was minted by Zenodo when v3.1.3 was released.

Expand Down
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,38 @@ Measuring campaign lift? Evaluating a product launch? diff-diff handles the caus
- **[Brand awareness survey tutorial](docs/tutorials/17_brand_awareness_survey.ipynb)** - Full example with complex survey design, brand funnel analysis, and staggered rollouts
- **Have BRFSS/ACS/CPS individual records?** Use [`aggregate_survey()`](docs/api/prep.rst) to roll respondent-level microdata into a geographic-period panel with inverse-variance precision weights. The returned second-stage design uses analytic weights (`aweight`), so it works directly with `DifferenceInDifferences`, `TwoWayFixedEffects`, `MultiPeriodDiD`, `SunAbraham`, `ContinuousDiD`, and `EfficientDiD` (estimators marked **Full** in the [survey support matrix](docs/choosing_estimator.rst))

### Experimental preview: `BusinessReport` and `DiagnosticReport`

diff-diff ships two preview classes, `BusinessReport` and `DiagnosticReport`, that produce plain-English output and a structured `to_dict()` schema from any fitted result. **Both are experimental in this release** — wording, verdict thresholds, and schema shape will change as the library learns from real practitioner usage. Do not anchor downstream tooling on the schema yet; the experimental flag is noted in the CHANGELOG.

```python
from diff_diff import CallawaySantAnna, BusinessReport

cs = CallawaySantAnna(base_period="universal").fit(
df, outcome="revenue", unit="store", time="month",
first_treat="first_treat", aggregate="event_study",
)
report = BusinessReport(
cs,
outcome_label="Revenue per store",
outcome_unit="$",
business_question="Did the loyalty program lift revenue?",
treatment_label="the loyalty program",
# Optional: pass the panel + column names so the auto-constructed
# DiagnosticReport can run data-dependent checks (2x2 pre-trends,
# Goodman-Bacon decomposition, EfficientDiD Hausman pretest).
# Without these the auto path still runs but skips those checks.
data=df,
outcome="revenue",
unit="store",
time="month",
first_treat="first_treat",
)
print(report.summary())
```

`BusinessReport` auto-constructs a `DiagnosticReport` so the summary mentions pre-trends, sensitivity, and design-effect findings in one call. Methodology (phrasing rules, verdict thresholds, schema stability) is documented in [docs/methodology/REPORTING.md](docs/methodology/REPORTING.md). Feedback on wording, applicability, and missing diagnostics is welcome — this is the part of the library most likely to evolve in the next few releases.

Already know DiD? The [academic quickstart](docs/quickstart.rst) and [estimator guide](docs/choosing_estimator.rst) cover the full technical details.

## Features
Expand Down
4 changes: 2 additions & 2 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ See [Survey Design Support](docs/choosing_estimator.rst#survey-design-support) f

Major landings since the prior roadmap revision. See [CHANGELOG.md](CHANGELOG.md) for the full history.

- **`BusinessReport` and `DiagnosticReport`** - practitioner-ready output layer. Plain-English stakeholder summaries + unified diagnostic runner with a stable AI-legible `to_dict()` schema. `BusinessReport` auto-constructs `DiagnosticReport` by default so summaries mention pre-trends, robustness, and design-effect findings in one call. Estimator-native validation surfaces are routed through: SyntheticDiD uses `pre_treatment_fit` / `in_time_placebo` / `sensitivity_to_zeta_omega`; EfficientDiD uses its native `hausman_pretest`; TROP exposes factor-model fit metrics. See `docs/methodology/REPORTING.md` for methodology deviations including no-traffic-light gates, pre-trends verdict thresholds, and power-aware phrasing.
- **ChaisemartinDHaultfoeuille (dCDH)** - full feature set: `DID_M` contemporaneous-switch, multi-horizon `DID_l` event study, analytical SE, multiplier bootstrap, TWFE decomposition diagnostic, dynamic placebos, normalized estimator, cost-benefit aggregate, sup-t bands, covariate adjustment (`DID^X`), group-specific linear trends (`DID^{fd}`), state-set-specific trends, heterogeneity testing, non-binary treatment, HonestDiD integration, and survey support (TSL + pweight).
- **SyntheticDiD jackknife variance** (`variance_method='jackknife'`) with survey-weighted jackknife.
- **SyntheticDiD validation diagnostics**.
Expand All @@ -78,8 +79,7 @@ Queued work, ordered by expected leverage. Each item is its own PR. Ordering is

### Practitioner-ready output

- **`BusinessReport` class.** Plain-English summaries of any estimator's results with markdown export. Optional rich formatting via a `[reporting]` extra; core remains numpy/pandas/scipy only. Turns raw coefficients into stakeholder-ready artifacts.
- **`DiagnosticReport` with context-aware `practitioner_next_steps()`.** Unified diagnostic runner that bundles parallel-trends, placebo, HonestDiD, Bacon decomposition, DEFF, EPV, and power diagnostics into one plain-English report. `practitioner_next_steps()` substitutes actual column names from fitted results instead of generic placeholders.
- **Context-aware `practitioner_next_steps()`.** Substitutes actual column names from fitted results instead of generic placeholders, so next-step guidance is executable rather than illustrative. (Standalone follow-up to the `BusinessReport` / `DiagnosticReport` landing below; tracked under the AI-Agent Track too.)

### Practitioner tutorials

Expand Down
16 changes: 16 additions & 0 deletions diff_diff/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,16 @@
plot_synth_weights,
)
from diff_diff.practitioner import practitioner_next_steps
from diff_diff.business_report import (
BUSINESS_REPORT_SCHEMA_VERSION,
BusinessContext,
BusinessReport,
)
from diff_diff.diagnostic_report import (
DIAGNOSTIC_REPORT_SCHEMA_VERSION,
DiagnosticReport,
DiagnosticReportResults,
)
from diff_diff._guides_api import get_llm_guide
from diff_diff.datasets import (
clear_cache,
Expand Down Expand Up @@ -405,6 +415,12 @@
"clear_cache",
# Practitioner guidance
"practitioner_next_steps",
"BusinessReport",
"BusinessContext",
"BUSINESS_REPORT_SCHEMA_VERSION",
"DiagnosticReport",
"DiagnosticReportResults",
"DIAGNOSTIC_REPORT_SCHEMA_VERSION",
# LLM guide accessor
"get_llm_guide",
]
Loading
Loading