Skip to content

Commit dc277e3

Browse files
authored
Merge pull request #257 from igerber/release/v2.8.3
Bump version to 2.8.3, add Phase 8 survey maturity roadmap
2 parents 006568b + b421259 commit dc277e3

File tree

6 files changed

+131
-5
lines changed

6 files changed

+131
-5
lines changed

CHANGELOG.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [2.8.3] - 2026-04-02
11+
12+
### Added
13+
- **Silent operation warnings** — 8 operations that previously altered analysis results without informing the user now emit `UserWarning`:
14+
- TROP lstsq → pseudo-inverse numerical fallback
15+
- TwoStageDiD NaN masking of unidentified fixed effects (zeroed out with treatment indicator)
16+
- TwoStageDiD always-treated unit removal (sample size change)
17+
- CallawaySantAnna silent (g,t) pair skipping (zero treated or control observations)
18+
- TROP missing treatment indicator fill with 0 (control)
19+
- Rust → Python backend fallback (previously debug log only)
20+
- Survey weight normalization (pweights/aweights rescaled to mean=1)
21+
- `np.inf` → 0 never-treated convention conversion
22+
- **ImputationDiD pre-period event study coefficients** — pre-treatment "effects" (should be ~0 under parallel trends) for visual pre-trends assessment, following BJS (2024) Test 1
23+
- **TwoStageDiD pre-period event study coefficients** — same pre-trends extension
24+
- **Replicate weight expansion** to 7 additional estimators: DifferenceInDifferences, TwoWayFixedEffects, MultiPeriodDiD, SunAbraham, StackedDiD, ImputationDiD, TwoStageDiD (coverage: 4/13 → 11/13)
25+
26+
### Changed
27+
- ImputationDiD pre-period coefficients use BJS Test 1 (impute Y(0) for treated units in pre-treatment periods)
28+
- SunAbraham replicate weights use full interaction-weighted refit per replicate with cohort-level SEs
29+
30+
### Fixed
31+
- Fix zero-weight demeaning safety in replicate weight paths
32+
- Fix `df_survey` writeback for rank-deficient replicate designs (df=0)
33+
- Fix ImputationDiD `balance_e` zero-qualifying-cohort fallback in pretrends path
34+
- Fix survey zero-mass (g,t) skip warning gap
35+
- Fix SunAbraham positional assignment in replicate loop
36+
1037
## [2.8.2] - 2026-04-02
1138

1239
### Added
@@ -1085,6 +1112,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
10851112
- `to_dict()` and `to_dataframe()` export methods
10861113
- `is_significant` and `significance_stars` properties
10871114

1115+
[2.8.3]: https://github.com/igerber/diff-diff/compare/v2.8.2...v2.8.3
10881116
[2.8.2]: https://github.com/igerber/diff-diff/compare/v2.8.1...v2.8.2
10891117
[2.8.1]: https://github.com/igerber/diff-diff/compare/v2.8.0...v2.8.1
10901118
[2.8.0]: https://github.com/igerber/diff-diff/compare/v2.7.6...v2.8.0

diff_diff/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@
210210
Bacon = BaconDecomposition
211211
EDiD = EfficientDiD
212212

213-
__version__ = "2.8.2"
213+
__version__ = "2.8.3"
214214
__all__ = [
215215
# Estimators
216216
"DifferenceInDifferences",

docs/llms-full.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
> A Python library for Difference-in-Differences causal inference analysis. Provides sklearn-like estimators with statsmodels-style output for econometric analysis.
44

5-
- Version: 2.8.2
5+
- Version: 2.8.3
66
- Repository: https://github.com/igerber/diff-diff
77
- License: MIT
88
- Dependencies: numpy, pandas, scipy (no statsmodels dependency)

docs/survey-roadmap.md

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Survey Data Support Roadmap
22

33
This document captures the survey data support roadmap for diff-diff.
4-
All phases (1-6) are implemented.
4+
Phases 1-7 are implemented. Phase 8 (maturity refinements) is planned.
55

66
## Implemented (Phases 1-2)
77

@@ -202,3 +202,101 @@ variance estimation for staggered triple differences.
202202

203203
**Reference:** Ortiz-Villavicencio, M. & Sant'Anna, P.H.C. (2025).
204204
"Better Understanding Triple Differences Estimators." arXiv:2505.09942.
205+
206+
---
207+
208+
## Phase 8: Survey Maturity
209+
210+
Refinements to close remaining gaps versus R's `survey` package and improve
211+
practitioner experience. Prioritized by user impact.
212+
213+
### 8a. Successive Difference Replication (SDR)
214+
215+
**Priority: High.** ACS PUMS — the most common US survey dataset for DiD
216+
policy evaluation — provides 80 SDR replicate weight columns. Without SDR
217+
support, these users can't use their provided replicate weights directly.
218+
219+
**What's needed:**
220+
- Add `"SDR"` to `valid_rep_methods` in `SurveyDesign`
221+
- Variance formula: `V = 4/R * sum((theta_r - theta)^2)` — a scaling
222+
difference from BRR, not a new algorithm
223+
- Wire through `compute_replicate_vcov()` and `compute_replicate_if_variance()`
224+
225+
**Reference:** Fay, R.E. & Train, G.F. (1995). "Aspects of Survey and
226+
Model-Based Postcensal Estimation of Income and Poverty Characteristics
227+
for States and Counties." ASA Proceedings.
228+
229+
### 8b. FPC in ImputationDiD and TwoStageDiD
230+
231+
**Priority: High.** Both estimators now support replicate weights and TSL
232+
with strata/PSU, but reject FPC outright (`NotImplementedError`). Adding
233+
FPC is incremental — thread `fpc` through the existing TSL variance path.
234+
Matters for finite population surveys (common in state-level sampling).
235+
236+
**Current gate:** `imputation.py:280`, `two_stage.py:268`
237+
238+
### 8c. Silent Operation Warnings
239+
240+
**Priority: High.** Add `UserWarning` emissions for operations that
241+
silently alter analysis results:
242+
- TROP lstsq → pseudo-inverse numerical fallback
243+
- TwoStageDiD NaN masking of unidentified fixed effects
244+
- TwoStageDiD always-treated unit removal
245+
- CallawaySantAnna silent (g,t) pair skipping
246+
- TROP missing treatment indicator fill with 0
247+
- Rust → Python backend fallback (currently debug log only)
248+
- Survey weight normalization (pweights rescaled to mean=1)
249+
- `np.inf` → 0 never-treated conversion
250+
251+
### 8d. Lonely PSU "adjust" in Bootstrap
252+
253+
**Priority: Medium.** `lonely_psu="adjust"` works for analytical (TSL)
254+
variance but raises `NotImplementedError` for survey-aware bootstrap
255+
(2 raises in `bootstrap_utils.py`). Real survey data regularly has
256+
singleton strata. Users needing bootstrap inference with such data hit
257+
a wall.
258+
259+
**Reference:** Rust, K.F. & Rao, J.N.K. (1996). "Variance Estimation
260+
for Complex Surveys Using Replication Techniques." Statistical Methods
261+
in Medical Research 5(3).
262+
263+
### 8e. Survey Diagnostics and Utilities
264+
265+
**Priority: Medium.** Small additions that signal maturity to survey
266+
statisticians:
267+
- **CV on estimates**: coefficient of variation (SE/estimate) on results
268+
objects — trivial to add, used by federal agencies for publication
269+
standards (NCHS requires CV < 30% for releasable estimates)
270+
- **Weight trimming**: `trim_weights(data, weight_col, upper=None,
271+
quantile=None)` utility in `prep.py` for capping extreme weights
272+
- **ImputationDiD pretrends + survey**: pre-trends F-test currently
273+
ignores survey variance (`NotImplementedError` at `imputation.py:240`)
274+
275+
### 8f. Survey Compatibility Matrix
276+
277+
**Priority: Medium.** Users discover survey support limits by hitting
278+
`NotImplementedError` at runtime. Add a table to the survey tutorial
279+
or `choosing_estimator.rst` showing which estimator × survey feature
280+
combinations are supported (weights, strata/PSU, FPC, replicate weights,
281+
bootstrap + survey).
282+
283+
### 8g. Documentation-Only Items
284+
285+
**Priority: Low.** No code changes required:
286+
- **Multi-stage design**: document that single-stage (strata + PSU)
287+
is sufficient for variance estimation per Lumley (2004) Section 2.2.
288+
Don't implement multi-stage — it adds complexity without changing
289+
results for DiD applications.
290+
- **Post-stratification / calibration**: document that `SurveyDesign`
291+
expects pre-calibrated weights. Point users to `samplics` or R's
292+
`survey::calibrate()` for weight calibration. This is data prep,
293+
not DiD estimation — out of scope.
294+
295+
### Deferred
296+
297+
| Estimator | Capability | Reason |
298+
|-----------|-----------|--------|
299+
| SyntheticDiD | Replicate weights | No published theory on replicate weights + unit weight optimization |
300+
| TROP | Replicate weights | No published theory on replicate weights + nuclear norm regularization |
301+
| BaconDecomposition | Replicate weights | Diagnostic tool with no inference — replicate weights don't apply |
302+
| EfficientDiD | Covariates + survey, cluster + survey, bootstrap + survey | Lower demand, newer estimator; 3 `NotImplementedError` paths |

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "maturin"
44

55
[project]
66
name = "diff-diff"
7-
version = "2.8.2"
7+
version = "2.8.3"
88
description = "Difference-in-Differences causal inference with sklearn-like API. Callaway-Sant'Anna, Synthetic DiD, Honest DiD, event studies, parallel trends."
99
readme = "README.md"
1010
license = "MIT"

rust/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "diff_diff_rust"
3-
version = "2.8.2"
3+
version = "2.8.3"
44
edition = "2021"
55
description = "Rust backend for diff-diff DiD library"
66
license = "MIT"

0 commit comments

Comments
 (0)