feat(v4): ContinuousDiD post-fit aggregate() - mixed view/recompute adopter (2(b) PR-3c, M-025) - #750
Merged
Merged
Conversation
…dopter (2(b) PR-3c, M-025) fit(aggregate=) deprecates via the NOT_SUPPLIED shim (sentinel-only normalization; the pre-existing value validation survives, and the "eventstudy" spelling dies with the param in 4.0). 'simple' (2 rows, att+acrt) and 'dose' (2N target-discriminated rows) are pure views over the always-computed curves/overalls - permitted on bootstrap fits, relaying stored inference verbatim incl. the finite overall t. 'event_study' recomputes from a pruned per-cell IF payload kit (scalars-only on bootstrap fits, which fail closed; replicate designs supported IF-based, no refit replay; panel-level survey ref by decision). The ES machinery moves verbatim to the new leaf module continuous_did_aggregation.py, shared by fit and the post-fit route. First heterogeneous-target AggregationResult: summary()/to_dataframe() gain the target column + first-appearance target-block ordering (uniform-target producers byte-stable; normative rule in v4-design §6). honest/pretrends terminal messages name the by-design ContinuousDiD rejection (no joint ES covariance; no reference normalization). Ledger: M-025 shimmed; M-092 qualifier + M-093 fifth amendment; REGISTRY ContinuousDiD Note 8; M-092/bootstrap-replay TODO rows. Contract tests: 49-test ContinuousDiD block (ES inertness 1e-14 across 13 design arms, view parity, isolation, scalars-only kit pin, no-kit legacy views, unsorted-dvals ordering, mixed-type-label fallback), consumer rejection pins, practitioner/guides pins. Sweep: tests (dose no-ops dropped, analytical ES sites migrated post-fit, invalid-value pin warns+raises), bench_dose_response (ES phase migrated post-fit), performance docs, practitioner HAD-handoff strings, tutorial 14 (incl. the downstream plot-consumer cell), llms guides, api rst, re-derived line anchors.
Overall Assessment: ✅ Looks goodExecutive Summary
Methodology
Code QualityNo findings. Performance
MaintainabilityNo findings. Tech Debt
SecurityNo findings or apparent secrets. The retained kit uses positional indices and resolved numerical survey structures rather than source panel columns or raw unit identifiers. Documentation / Tests
Test coverage is extensive across anticipation, controls, survey/replicate designs, bootstrap gating, empty results, and NaN inference. Static AST parsing passed; executable tests could not run because NumPy is unavailable in the review environment. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ContinuousDiD.fit(aggregate=)deprecates via the sharedNOT_SUPPLIEDsentinel - a plainfit()never warns, any supplied value (incl.None) warns once, the legacy routing runs unchanged until 4.0, and the PRE-EXISTING fit-time value validation survives (unknown strings still raiseValueErrorafter the warning; the no-underscore"eventstudy"spelling dies with the param).aggregate()- unique among the adopters: the dose-response curves and the overall binarized ATT (ATT^{loc}under PT; equalsATT^{glob}under SPT) plusACRT^{glob}are ALWAYS computed byfit()(aggregate="dose"was a fit-time no-op), soaggregate('simple')(2 rows, targetsatt/acrt; n = disjoint treated+control unit total,n_kind='units') andaggregate('dose')(2N target-discriminated rows over the dose grid) are pure VIEWS relaying stored inference verbatim - permitted on bootstrap fits (the dCDH per-level reasoning), including the stored FINITE overall t beside percentile p/CI.aggregate('event_study')RECOMPUTES the binarized event study from a pruned per-cell IF payload kit; bootstrap fits carry a scalars-only kit and fail closed; replicate-weight designs are supported post-fit (IF-based, no refit replay).diff_diff/continuous_did_aggregation.py:_aggregate_event_studymoved verbatim + fit's inline analytical ES-SE block extracted as_compute_event_study_inference, shared by fit-time and the post-fit kit route (import DAG: the results module cannot import the estimator module).targetAggregationResult:summary()gains atargetcolumn + neutralestimateheading when targets are mixed;to_dataframe()orders heterogeneous-target rows by first-appearance target blocks (att before acrt) with labels ascending within block under the existing_sortableguard - uniform-target producers render byte-identically. Normative rule added todocs/v4-design.mdsection 6.compute_honest_did/compute_pretrends_powerreject ContinuousDiD containers BY DESIGN (no joint event-study covariance; the binarized bins carry no reference-period normalization) - both terminal messages now say so (M-093 fifth amendment).shimmed(register-style notes), M-092 scope qualifier extended (scalardf_surveyonly; per-row df tracked in the existing TODO row, now naming ContinuousDiD), REGISTRY ContinuousDiD Note 8, AggregationKit docstring pruned-payload variant, bootstrap-ES-replay TODO row.aggregate="dose"kwargs dropped, analytical ES sites migrated post-fit, the invalid-value pin now pins warn-then-raise, bootstrap-ES sites kept fit-time under module suppression),bench_dose_response.py(ES phase migrated post-fit so it keeps timing the event study), performance docs, practitioner HAD-handoff guidance strings, tutorial 14 (incl. the downstream plot-consumer cell's schema), llms guides, API rst; allcontinuous_did.py:line anchors re-derived symbol-by-symbol (two were already stale).Methodology references (required if estimator / math changes)
ATT^{es}_{loc}(e)construction;docs/methodology/REGISTRY.md§ ContinuousDiD.Validation
tests/test_aggregate_contract.py(new 49-test ContinuousDiD block: shim pins, ES inertness at 1e-14 across plain/multi-cohort/anticipation/covariates/survey-TSL/zero-dose-drop/replicate(healthy,dropped,undefined-df)/discrete/lowest-dose/not-yet-treated/non-default-config arms, per-curve dose parity, bit-exact simple relay incl. the finite bootstrap t, heterogeneous-target rendering incl. an unsorted-dvalsordering arm and a mixed-type-label fallback arm, isolation incl. theres.n_bootstrap = 0gate-bypass arm, scalars-only bootstrap kit, no-kit legacy views, vocabulary fail-closed, pickle round-trip, no-raw-identifier retention),tests/test_event_study_consumers.py(real-container rejection via both consumers),tests/test_practitioner.py+tests/test_guides.py(M-025 pins;_assert_shim_linesgained an optionalbal_row), plus the migrated sites intests/test_continuous_did.py,tests/test_methodology_continuous_did.py(benchmark 6 keeps exercising the ES route post-fit),tests/test_survey_phase3.py,tests/test_profile_panel.py.docs/tutorials/14_continuous_did.ipynbmigrated to the post-fit route (analytical ES fit; downstream plot cell on the unified schema) and re-executed clean via nbmake. R-parity/benchmark numbers unchanged (the harness now exercises the ES route post-fit). Perf: fit timing bands overlap PRE/POST; pickle deltas are the documented kit retention (+79 KB plain / +171 KB TSL survey / +315 KB replicate on the 300x10 benchmark panel; scalars-only on bootstrap fits).Security / privacy