Add LPDiD complex-survey R-parity validation vs survey::svyglm (Phase D2)#591
Conversation
|
Overall Assessment ✅ Looks good — no unmitigated P0/P1 findings. This PR is validation/documentation-only for Executive Summary
Methodology
No undocumented methodology mismatch found. The generator builds event-study and pooled Code Quality
Performance
Maintainability
Tech Debt
Security
Documentation/Tests
Verification limitation: targeted pytest could not run because |
…(Phase D2)
Pin the merged D1 LPDiD survey path end-to-end against survey::svyglm (Lumley)
goldens on a dedicated staggered-absorbing survey panel. Closes Phase D of the
LP-DiD salvage initiative. No diff_diff/ change (verify-and-document).
Three structurally-distinct survey variance paths are R-validated per-horizon
(point/SE/df) + pooled-post/pre:
* VW full design (strata + PSU + FPC) vs svyglm(ids=~psu, strata, fpc, weights);
df = n_PSU - n_strata = 10.
* weights-only, unit injected as PSU vs svyglm(ids=~unit, weights); df = n_PSU - 1.
* direct covariate inclusion vs svyglm(Dy ~ tr + x + factor(time)).
Each LP-DiD horizon uses a FRESH svydesign over that horizon's clean long-difference
sample (matching the library's per-sample resolution, not subset() of a full design).
svyglm is the reference implementation of the Binder TSL sandwich, so it anchors the
variance directly; the clean-sample construction is independently cross-checked against
alexCardazzi/lpdid (unweighted VW event study matches to <1e-8), and every svyglm WLS
point is gated == weighted feols on the same sample (<1e-7).
Tolerances: point abs=1e-6, SE rtol=1e-5/abs=1e-7, df exact. New
TestLPDiDSurveyParityR + generate_lpdid_survey_golden.R + lpdid_survey_panel.csv /
lpdid_survey_golden.json (own seed -> absorbing/non-absorbing goldens byte-identical).
REGISTRY Deviation #8 + checklist upgraded to "validated vs svyglm"; CHANGELOG; TODO row closed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
e6a0d96 to
ad053ff
Compare
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment ✅ Looks good — no unmitigated P0/P1 findings. This PR is validation/documentation-only for Executive Summary
Methodology
No undocumented methodology mismatch found. Code Quality No findings. The added test helpers are narrowly scoped, assert point/SE/df/n_PSU separately, and do not introduce inline inference computation or estimator-side parameter propagation changes. Performance No findings. The committed fixture is small, and the repeated LPDiD fits are test-only methodology validation. Maintainability No findings. The generator is deterministic, writes disjoint survey fixture paths, pins the external Tech Debt
Security No findings. A secret-pattern scan over changed files did not flag credentials, and the added data appears synthetic. Documentation/Tests No findings. CHANGELOG, TODO, REGISTRY, generator, golden JSON, panel CSV, and parity tests are aligned. Verification limitation: |
Summary
LPDiDcomplex-survey path againstsurvey::svyglm(Lumley). Verify-and-document only — nodiff_diff/change. Closes Phase D.benchmarks/R/generate_lpdid_survey_golden.R+ committedlpdid_survey_panel.csv/lpdid_survey_golden.json(own seed, so the absorbing / non-absorbing goldens stay byte-identical).TestLPDiDSurveyParityRpins three structurally-distinct survey variance paths end-to-end throughLPDiD.fit(survey_design=...), each per-horizon (point/SE/df) + pooled-post/pre:svyglm(ids=~psu, strata, fpc, weights);df = n_PSU - n_strata(= 10).svyglm(ids=~unit, weights);df = n_PSU - 1(= 139).svyglm(Dy ~ tr + x + factor(time), ...).svydesignover that horizon's clean long-difference sample (matching the library's per-samplesurvey_design.resolve(sample), notsubset()of a full design).svyglmis the reference implementation of the Binder TSL sandwich, so it anchors the variance directly; the clean-sample construction is independently cross-checked againstalexCardazzi/lpdid(the unweighted VW event study matches to <1e-8), and everysvyglmWLS point is gated==weightedfeolson the same sample (<1e-7).## LPDiDDeviation Add Synthetic Difference-in-Differences (SDID) estimator #8 + checklist upgraded to "validated vssurvey::svyglm"; CHANGELOG entry; D2 TODO row closed.Methodology references
LPDiDcomplex-survey variance (Binder 1983 stratified-PSU Taylor-linearization sandwich). No estimator or default-behavior change — this PR validates the merged D1 path.survey::svyglm(Lumley 2004).svyglmis itself the reference TSL implementation, so it anchors the variance directly (no third-party survey package gate needed). Documented indocs/methodology/REGISTRY.md## LPDiDDeviation Add Synthetic Difference-in-Differences (SDID) estimator #8.Validation
tests/test_methodology_lpdid.py(TestLPDiDSurveyParityR: VW ES+pooled, weights-only inject, direct-covariate, FPC-shrinks-SE, weighting-flows). Tolerances: pointabs=1e-6, SErtol=1e-5/abs=1e-7, df exact. 17/17 pure-Python + 5/5 Rust green; existing LPDiD parity classes unchanged.feols == svyglmpoint gate, no-lonely-PSU guard. Existinglpdid_test_panel.csv/lpdid_golden.json/lpdid_nonabsorbing_*confirmed byte-identical.Security / privacy
Generated with Claude Code