Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- **LPDiD estimator** (`LPDiD`) for the absorbing-treatment main path of Stata `lpdid`
- Event-study and pooled pre/post effects with clean controls or never-treated controls
- `rw` and `nocomp` support with official Stata parity tests on bundled example data
- `pmd(max|k)`, covariates, `ylags`, `dylags`, and additional absorbed fixed effects
- Regression-adjustment parity for `rw + controls/absorb/ylags/dylags` on focused Stata-validated samples

### Changed
- Move Local Projections DiD from roadmap item to implemented estimator in public documentation

## [2.8.0] - 2026-03-31

### Added
Expand Down
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ Detailed guide: [`docs/llms-practitioner.txt`](docs/llms-practitioner.txt)
- **Panel data support**: Two-way fixed effects estimator for panel designs
- **Multi-period analysis**: Event-study style DiD with period-specific treatment effects
- **Staggered adoption**: Callaway-Sant'Anna (2021), Sun-Abraham (2021), Borusyak-Jaravel-Spiess (2024) imputation, Two-Stage DiD (Gardner 2022), Stacked DiD (Wing, Freedman & Hollingsworth 2024), and Efficient DiD (Chen, Sant'Anna & Xie 2025) estimators for heterogeneous treatment timing
- **Local Projections DiD**: `LPDiD` for absorbing-treatment event studies and pooled effects, with clean controls, `rw`, `nocomp`, `pmd`, covariates, lags, and additional absorbed fixed effects
- **Triple Difference (DDD)**: Ortiz-Villavicencio & Sant'Anna (2025) estimators with proper covariate handling
- **Synthetic DiD**: Combined DiD with synthetic control for improved robustness
- **Triply Robust Panel (TROP)**: Factor-adjusted DiD with synthetic weights (Athey et al. 2025)
Expand Down Expand Up @@ -117,9 +118,42 @@ All estimators have short aliases for convenience:
| `Stacked` | `StackedDiD` | Stacked DiD |
| `Bacon` | `BaconDecomposition` | Goodman-Bacon decomposition |
| `EDiD` | `EfficientDiD` | Efficient DiD |
| `LPDiD` | `LPDiD` | Local Projections DiD |

`TROP` already uses its short canonical name and needs no alias.

## Local Projections DiD

`LPDiD` ports the absorbing-treatment main path of Stata's `lpdid` command into
the `diff-diff` estimator interface. It supports dynamic event-study effects and
pooled pre/post effects with clean controls or never-treated controls, optional
reweighting (`rw`), common-composition samples (`nocomp`), pre-mean
differencing (`pmd`), covariates, outcome lags, first-difference lags, and
additional absorbed fixed effects.

```python
from diff_diff import LPDiD

res = LPDiD(
pre_window=5,
post_window=10,
reweight=True,
no_composition=True,
).fit(
data,
outcome="Y",
unit="unit",
time="time",
treatment="treat",
)

print(res.event_study.head())
print(res.pooled)
```

The current implementation is validated against official Stata `lpdid`
absorbing-treatment examples and option paths used in the test suite.

## Tutorials

We provide Jupyter notebook tutorials in `docs/tutorials/`:
Expand All @@ -140,6 +174,7 @@ We provide Jupyter notebook tutorials in `docs/tutorials/`:
| `12_two_stage_did.ipynb` | Two-Stage DiD (Gardner 2022), GMM sandwich variance, per-observation effects |
| `13_stacked_did.ipynb` | Stacked DiD (Wing et al. 2024), Q-weights, sub-experiment inspection, trimming, clean control definitions |
| `15_efficient_did.ipynb` | Efficient DiD (Chen et al. 2025), optimal weighting, PT-All vs PT-Post, efficiency gains, bootstrap inference |
| `16_lpdid.ipynb` | LPDiD for absorbing treatments, official Stata `lpdid` example workflow, `rw`, `nocomp`, and event-study plotting |

## Data Preparation

Expand Down
25 changes: 14 additions & 11 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ For past changes and release history, see [CHANGELOG.md](CHANGELOG.md).

diff-diff v2.7.5 is a **production-ready** DiD library with feature parity with R's `did` + `HonestDiD` + `synthdid` ecosystem for core DiD analysis, plus **unique survey support** — design-based variance estimation (Taylor linearization, replicate weights) integrated across all estimators. No R or Python package offers this combination:

- **Core estimators**: Basic DiD, TWFE, MultiPeriod, Callaway-Sant'Anna, Sun-Abraham, Borusyak-Jaravel-Spiess Imputation, Synthetic DiD, Triple Difference (DDD), TROP, Two-Stage DiD (Gardner 2022), Stacked DiD (Wing et al. 2024), Continuous DiD (Callaway, Goodman-Bacon & Sant'Anna 2024)
- **Core estimators**: Basic DiD, TWFE, MultiPeriod, Callaway-Sant'Anna, Sun-Abraham, Borusyak-Jaravel-Spiess Imputation, Synthetic DiD, LPDiD, Triple Difference (DDD), TROP, Two-Stage DiD (Gardner 2022), Stacked DiD (Wing et al. 2024), Continuous DiD (Callaway, Goodman-Bacon & Sant'Anna 2024)
- **Valid inference**: Robust SEs, cluster SEs, wild bootstrap, multiplier bootstrap, placebo-based variance
- **Assumption diagnostics**: Parallel trends tests, placebo tests, Goodman-Bacon decomposition
- **Sensitivity analysis**: Honest DiD (Rambachan-Roth), Pre-trends power analysis (Roth 2022)
Expand Down Expand Up @@ -50,6 +50,19 @@ Extend the existing `TripleDifference` estimator to handle staggered adoption se

**Reference**: [Ortiz-Villavicencio & Sant'Anna (2025)](https://arxiv.org/abs/2505.09942). "Better Understanding Triple Differences Estimators." *Working Paper*. R package: `triplediff`.

### Local Projections DiD

The absorbing-treatment main path is now implemented as `LPDiD`, including
event-study and pooled effects, clean vs never-treated controls, `rw`,
`nocomp`, `pmd`, covariates, lags, and additional absorbed fixed effects with
Stata-validated parity coverage.

Remaining work is now narrower and more specialized:

- nonabsorbing-treatment support
- bootstrap inference parity for LPDiD-specific paths
- broader documentation examples

---

## Medium-Term Enhancements
Expand All @@ -70,16 +83,6 @@ Handles treatment that switches on and off (reversible treatments), unlike most

**Reference**: [de Chaisemartin & D'Haultfœuille (2020, 2024)](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3980758). *American Economic Review*.

### Local Projections DiD

Implements local projections for dynamic treatment effects. Doesn't require specifying full dynamic structure.

- Flexible impulse response estimation
- Robust to misspecification of dynamics
- Natural handling of anticipation effects

**Reference**: Dube, Girardi, Jordà, and Taylor (2023).

### Nonlinear DiD

For outcomes where linear models are inappropriate (binary, count, bounded).
Expand Down
8 changes: 8 additions & 0 deletions diff_diff/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
Comparison2x2,
bacon_decompose,
)
from diff_diff.lpdid import (
LPDiD,
)
from diff_diff.diagnostics import (
PlaceboTestResults,
leave_one_out_test,
Expand Down Expand Up @@ -102,6 +105,9 @@
PeriodEffect,
SyntheticDiDResults,
)
from diff_diff.lpdid_results import (
LPDiDResults,
)
from diff_diff.survey import (
DEFFDiagnostics,
SurveyDesign,
Expand Down Expand Up @@ -224,6 +230,7 @@
"TripleDifference",
"TROP",
"StackedDiD",
"LPDiD",
# Estimator aliases (short names)
"DiD",
"TWFE",
Expand Down Expand Up @@ -269,6 +276,7 @@
"trop",
"StackedDiDResults",
"stacked_did",
"LPDiDResults",
# EfficientDiD
"EfficientDiD",
"EfficientDiDResults",
Expand Down
Loading