Skip to content

Commit 03f08d9

Browse files
docs: add 0.7.0 CHANGELOG + csdid/differences parity table in README
Make the last five rounds of DiD work externally visible. CHANGELOG.md * Add a 0.7.0 release block (2026-04-14) summarising: aggte() unified aggregation, Mammen multiplier bootstrap w/ uniform bands, balance_e / min_e / max_e, anticipation, cs_report(), ggdid(), dCDH joint placebo + avg cumulative effect, Sun-Abraham rewritten with cluster sandwich SEs, and honest_did polymorphism. * Full reference list for every cited paper. README.md * Add `sp.aggte`, `sp.cs_report`, `sp.ggdid` rows to the DiD feature table. * Add a new "DiD parity with csdid / differences / R did + HonestDiD" comparison matrix (12 capabilities × 4 packages), making the from- paper reimplementation commitment explicit. Also export `aggte`, `cs_report`, `CSReport`, `ggdid` at the top-level statspai namespace so `sp.aggte(...)` / `sp.cs_report(...)` / `sp.ggdid(...)` work without any submodule dance. (The bare `sp.did` name has always resolved to the `did()` dispatch function in this package, not the submodule — pre-existing shadowing, unchanged here.) Verified: 114/114 DiD tests still green. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 26c8818 commit 03f08d9

3 files changed

Lines changed: 85 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,66 @@
22

33
All notable changes to StatsPAI will be documented in this file.
44

5+
## [0.7.0] - 2026-04-14
6+
7+
Focused release reaching feature parity with the R `did` / `HonestDiD`
8+
packages and the Python `csdid` / `differences` packages for staggered
9+
Difference-in-Differences. All core algorithms are reimplemented from
10+
the original papers — **no wrappers, no runtime dependencies on upstream
11+
DID packages**. DiD test count: 47 → 114.
12+
13+
### Added
14+
15+
- **`sp.did.aggte(result, type=...)`** — unified aggregation layer for
16+
`callaway_santanna()` results. Four aggregation schemes (`simple`,
17+
`dynamic`, `group`, `calendar`) backed by a single weighted-influence-
18+
function engine. Callaway & Sant'Anna (2021) Section 4.
19+
- **Mammen (1993) multiplier bootstrap** — IQR-rescaled pointwise
20+
standard errors *and* simultaneous (uniform / sup-t) confidence bands
21+
over the aggregation dimension. Matches the uniform-band behaviour
22+
of the R `did::aggte` function.
23+
- **`balance_e` / `min_e` / `max_e`** — event-study cohort balancing
24+
and window truncation (CS2021 eq. 3.8).
25+
- **`anticipation=δ`** parameter on `callaway_santanna()` — shifts the
26+
base period back by δ periods per CS2021 §3.2.
27+
- **`sp.did.cs_report(data, ...)`** — one-call report card. Runs the
28+
full pipeline (ATT(g,t) → four aggregations with uniform bands →
29+
pre-trend Wald → Rambachan-Roth breakdown M\* for every post event
30+
time) under a single bootstrap seed and pretty-prints the result.
31+
Returns a structured `CSReport` dataclass.
32+
- **`sp.did.ggdid(result)`** — plot routine for `aggte()` output,
33+
mirroring R `did::ggdid`. Auto-dispatches on aggregation type;
34+
uniform band overlaid on pointwise CI.
35+
- **dCDH joint inference** (`did_multiplegt`) — `joint_placebo_test`
36+
(Wald χ² across placebo lags with bootstrap covariance, dCDH 2024
37+
§3.3) and `avg_cumulative_effect` (mean of dynamic[0..L] with
38+
SE preserving cross-horizon covariance, dCDH 2024 §3.4).
39+
40+
### Changed
41+
42+
- **`sun_abraham()` inference layer rewritten** — replaces the former
43+
ad-hoc `√(σ²/(total·T))` approximation with a Liang-Zeger cluster-
44+
robust sandwich `(X'X)⁻¹ Σ_c X_c' u_c u_c' X_c (X'X)⁻¹` (small-sample
45+
adjusted), delta-method IW aggregation SEs `w' V_β w`, iterative
46+
two-way within transformation (correct on unbalanced panels), and
47+
optional `control_group='lastcohort'` per SA 2021 §6.
48+
- **`sp.did.honest_did()` / `breakdown_m()` made polymorphic** — now
49+
accept both the legacy `callaway_santanna()` / `sun_abraham()` result
50+
format (event study in `model_info`) and the new `aggte(type='dynamic')`
51+
format (event study in `detail` with Mammen uniform bands). The
52+
idiomatic pipeline `cs → aggte → honest_did → breakdown_m` now runs
53+
end-to-end with no manual plumbing.
54+
55+
### References
56+
57+
- Callaway, B. and Sant'Anna, P.H.C. (2021). *J. of Econometrics* 225(2).
58+
- Sun, L. and Abraham, S. (2021). *J. of Econometrics* 225(2).
59+
- Mammen, E. (1993). *Ann. Statist.* 21(1).
60+
- Liang, K.-Y. and Zeger, S.L. (1986). *Biometrika* 73(1).
61+
- de Chaisemartin, C. and D'Haultfoeuille, X. (2020). *AER* 110(9).
62+
- de Chaisemartin, C. and D'Haultfoeuille, X. (2024). *RESt*, forthcoming.
63+
- Rambachan, A. and Roth, J. (2023). *Rev. Econ. Studies* 90(5).
64+
565
## [0.6.2] - 2026-04-12
666

767
### Added

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,30 @@ It brings R's [Causal Inference Task View](https://cran.r-project.org/web/views/
157157
| `did_multiplegt()` | DID with treatment switching | de Chaisemartin & D'Haultfoeuille (2020) |
158158
| `did_imputation()` | Imputation DID estimator | Borusyak, Jaravel & Spiess (2024) |
159159
| `distributional_te()` | Distributional treatment effects | Chernozhukov, Fernandez-Val & Melly (2013) |
160+
| `sp.aggte()` | Unified aggregation for staggered DID (simple/dynamic/group/calendar) with Mammen multiplier-bootstrap uniform bands | Callaway & Sant'Anna (2021) §4; Mammen (1993) |
161+
| `sp.cs_report()` | One-call Callaway–Sant'Anna report: estimation + four aggregations + pre-trend test + Rambachan–Roth breakdown M\* | CS2021 + RR2023 |
162+
| `sp.ggdid()` | `aggte()` visualiser with uniform-band overlay | mirrors R `did::ggdid` |
163+
164+
#### DiD parity with `csdid` / `differences` / R `did` + `HonestDiD`
165+
166+
All algorithms below are reimplemented from the original papers — no
167+
wrappers, no runtime dependencies on upstream DID packages.
168+
169+
| Feature | StatsPAI | `csdid` (Py) | `differences` (Py) | R `did` |
170+
| --- | :---: | :---: | :---: | :---: |
171+
| Callaway–Sant'Anna ATT(g,t) with DR / IPW / REG |||||
172+
| Never-treated / not-yet-treated control group |||||
173+
| Anticipation (`anticipation=δ`) |||||
174+
| `aggte`: simple / dynamic / group / calendar |||||
175+
| Mammen multiplier bootstrap, uniform sup-t bands |||||
176+
| `balance_e` / `min_e` / `max_e` ||| partial ||
177+
| Sun–Abraham IW with Liang–Zeger cluster SE |||| via `fixest::sunab` |
178+
| Borusyak–Jaravel–Spiess imputation + pre-trend Wald |||| via `didimputation` |
179+
| de Chaisemartin–D'Haultfoeuille switch-on-off |||| via `DIDmultiplegtDYN` |
180+
| dCDH joint placebo Wald + avg. cumulative effect |||| ✅ (v2) |
181+
| Rambachan–Roth sensitivity + breakdown M\* |||| via `HonestDiD` |
182+
| `cs ⇄ aggte ⇄ honest_did` pipeline (single object) || partial | partial | partial |
183+
| One-call report card (`cs_report`) |||| via `summary()` |
160184

161185
### Regression Discontinuity
162186

src/statspai/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
parallel_trends_plot, bacon_plot, group_time_plot, did_plot,
4040
enhanced_event_study_plot, treatment_rollout_plot,
4141
sensitivity_plot, cohort_event_study_plot,
42+
aggte, cs_report, CSReport, ggdid,
4243
)
4344
from .rd import rdrobust, rdplot, rdplotdensity, rdbwsensitivity, rdbalance, rdplacebo, rdsummary, rkd, rd_honest, rdit
4445
from .synth import (

0 commit comments

Comments
 (0)