refactor(had): remove deprecated survey=/weights= kwargs from HeterogeneousAdoptionDiD.fit (3.7.0)#633
Conversation
…eneousAdoptionDiD.fit (3.7.0) Remove the deprecated `survey=` and `weights=` kwargs from `HeterogeneousAdoptionDiD.fit()`; `survey_design=` is now the sole weighting entry (design-based Binder-1983 Taylor-linearization variance), matching CallawaySantAnna / EfficientDiD / ImputationDiD / TwoStageDiD. `cband` is now keyword-only (it followed the removed positional slots). The pweight / CCT-2014 dispatch branches are provably dead once `weights=` is gone (weights_unit_full is not None iff resolved_survey_unit_full is not None), so they are deleted along with the metadata-clearing and pweight variance_formula labels. `variance_formula` is now one of None / "survey_binder_tsl" / "survey_binder_tsl_2sls". The survey_design= and unweighted paths are unchanged (byte-identical); ATT is unchanged on every surface. Migration: `survey=SurveyDesign(...)` -> `survey_design=SurveyDesign(...)` (pure rename); `fit(weights=<array>)` -> weight column + `survey_design=SurveyDesign( weights='col')` (SE moves from pweight/Normal to Binder-TSL/t(df); ~0.1%+); `fit(weights=w, cluster=c)` -> `survey_design=SurveyDesign(weights='w', psu='c')`. Docs (CHANGELOG ### Removed, REGISTRY notes, had.rst, llms-full, troubleshooting) and tests are updated to the survey_design=-only contract; the clustering-migration guidance is `survey_design=SurveyDesign(weights=, psu=)` (a HAD survey design without a weights column is rejected). Removed-kwarg tests now assert TypeError. Scope: HeterogeneousAdoptionDiD.fit() only. The 7 HAD pretest helpers keep the deprecated aliases pending a follow-up removal (each has its own weight back-end; tracked in TODO.md). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LHDijzf8zHXk5T8ahS2mKi
|
Overall Assessment ✅ Looks good. No unmitigated P0/P1 findings. Executive Summary
Methodology
Code Quality No findings. Performance No findings. Removing dead pweight branches should reduce branching and avoids extra synthetic survey metadata construction. Maintainability No blocking findings. The remaining pretest-helper cleanup is explicitly tracked in Tech Debt
Security No findings. Documentation/Tests
|
…the mass-point survey path) The mass-point `survey_design=` path emits `variance_formula="survey_binder_tsl_2sls"` only under `vcov_type="hc1"` / `robust=True`: it rejects `vcov_type="classical"` (had.py:3714) and rejects `cluster=` + `survey_design=` (had.py:3678), so PSU clustering is expressed via `SurveyDesign(psu=...)`, not `vcov_type="cr1"`. The result-field / to_dict docstrings and the llms-full variance_formula rows wrongly carried the old pweight_2sls "applied uniformly across classical / HC1 / CR1" framing onto the survey_binder_tsl_2sls label; reword to the hc1-only contract. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LHDijzf8zHXk5T8ahS2mKi
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment ✅ Looks good. No unmitigated P0/P1 findings. Executive Summary
Methodology
Code Quality No findings. Performance No findings. Removing the dead pweight branches reduces conditional surface area. Maintainability No blocking findings. The remaining seven HAD pretest-helper aliases are explicitly tracked as deferred work in Tech Debt
Security No findings. Documentation/Tests
Verification note: I could not run tests locally because this environment lacks |
…rthand A HAD survey design without a weights column is rejected, so the clustering shorthand in the survey_binder_tsl_2sls result-field / llms-full descriptions must be `SurveyDesign(weights='<weight_col>', psu='<cluster_col>')`, not a bare `SurveyDesign(psu=...)` (matches the had.rst wording). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LHDijzf8zHXk5T8ahS2mKi
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment ✅ Looks good. No unmitigated P0/P1 findings. Executive Summary
Methodology
Code Quality No findings. Performance No findings. Removing dead pweight branches reduces branching surface. Maintainability No blocking findings. Remaining HAD pretest-helper alias cleanup is tracked in Tech Debt
Security No findings. Documentation/Tests
Verification note: I could not run pytest or import the package because this environment lacks |
…ng_estimator + tutorial 20 Two doc surfaces outside the core diff still described the removed `HeterogeneousAdoptionDiD.fit(weights=)` shortcut and `pweight`/`pweight_2sls` labels, made stale by the 3.7.0 removal: - `choosing_estimator.rst`: rewrite the HAD SE-regime cell from three regimes (incl. the deprecated weights= shortcut + pweight labels) to the two-regime contract (unweighted vs `survey_design=` Binder-TSL; classical/cluster+survey fail-closed). - `20_had_brand_campaign.ipynb`: the Extensions note said the `weights=`/`survey=` aliases "will be removed in the next minor release" -> now removed; point to `survey_design=`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LHDijzf8zHXk5T8ahS2mKi
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment ✅ Looks good. No unmitigated P0/P1 findings. Executive Summary
Methodology
Code Quality No findings. The removed kwargs are absent from the public Performance No findings. Removing dead pweight shortcut branches reduces branching and metadata construction work. Maintainability No findings. Remaining internal Tech Debt
Security No findings. Documentation/Tests No blocking findings. The previous stale references to removed |
Summary
survey=andweights=kwargs fromHeterogeneousAdoptionDiD.fit();survey_design=is now the sole weighting entry (design-based Binder-1983 Taylor-linearization variance), matchingCallawaySantAnna/EfficientDiD/ImputationDiD/TwoStageDiD.cbandis now keyword-only (it previously followed the removed positionalsurvey/weightsslots).weights=is gone (weights_unit_full is not Noneiffresolved_survey_unit_full is not None), so they are deleted along with the metadata-clearing and pweightvariance_formulalabels.variance_formulais now one ofNone/"survey_binder_tsl"/"survey_binder_tsl_2sls". Thesurvey_design=and unweighted paths are byte-identical; ATT is unchanged on every surface (net -717 lines: dead branches + obsolete tests removed).HeterogeneousAdoptionDiD.fit()only. The 7 HAD pretest helpers keep the deprecated aliases pending a follow-up removal (each has its own weight back-end; tracked inTODO.md).Migration
survey=SurveyDesign(...)->survey_design=SurveyDesign(...)(pure rename; byte-identical output).fit(weights=<array>)-> add the weights as a column +survey_design=SurveyDesign(weights='col'). This is a variance-family change: pweight-robust / Normal -> Binder-TSL / t(df_survey) (SE moves ~0.1%+; ATT unchanged).fit(weights=w, cluster=c)->survey_design=SurveyDesign(weights='w', psu='c')(Binder-TSL clustered through the PSU).Methodology references (required if estimator / math changes)
HeterogeneousAdoptionDiD— de Chaisemartin, Ciccia, D'Haultfœuille & Knau (2026), arXiv:2405.04465v6; survey variance via Binder (1983) Taylor-series linearization through the sharedcompute_survey_if_variance.DeprecationWarningshipped ("will be removed in the next minor release"). Thefit(weights=<array>)->survey_design=migration is a documented variance-family change (pweight/Normal -> Binder-TSL/t(df)). See CHANGELOG### Removedand REGISTRY "Note (HAD survey-design API consolidation)".Validation
test_had_dual_knob_deprecation.py(removed kwargs ->TypeError;cbandkeyword-only; obsolete alias-parity tests dropped); migrated the weighted-behavior tests intest_had.py,test_had_mc.py,test_methodology_had.py,test_had_pretests.pyfromweights=/survey=tosurvey_design=(ATT bit-parity kept; SE relaxed to finite/positive only where the survey variance family legitimately differs); updatedtest_guides.py/test_practitioner.pyenumeration guards (variance_formulalabels 4 -> 2). Full HAD suite green;mypyat baseline (183);black/ruffclean.Security / privacy
🤖 Generated with Claude Code
https://claude.ai/code/session_01LHDijzf8zHXk5T8ahS2mKi