Fix TWFE within-transformation bug and add methodology review#139
Fix TWFE within-transformation bug and add methodology review#139
Conversation
The interaction term D_i × Post_t was not being within-transformed before regression, causing incorrect ATT estimates (~1/3 of true value) for multi-period panels with binary post indicator. Fixed by applying the same within-transformation to the interaction term, matching R's fixest::feols(). Also adds comprehensive methodology review: 33 tests across 6 phases (algebra verification, R comparison, edge cases, SE verification, wild bootstrap, params/results), TWFE benchmarks, and documentation updates. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Overall Assessment Executive Summary
Methodology
Code Quality
Performance
Maintainability
Tech Debt
Security
Documentation/Tests
|
…ixest coeftable - Merge two within-transform passes into one call (P3 perf fix) - Fix HC1 SE test to demean by unit+post (not period) matching TWFE - Rewrite SE test as cluster-vs-HC1 difference check with manual cluster verification - Use fixest coeftable() for R p-value instead of manual pt() computation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
/ai-review |
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall assessment:
|
The staggered treatment warning in _check_staggered_treatment only fires when `time` has >2 unique values. With binary `time="post"`, all treated units appear at time=1, making staggering undetectable. This updates docs, tests, and the registry to honestly reflect this limitation rather than claiming it as verified. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
/ai-review |
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall assessment: Executive summary:
Methodology
Code Quality
Performance
Maintainability
Tech Debt
Security
Documentation/Tests
|
- Add UserWarning in TWFE fit() when time column has >2 unique values, advising users to create a binary post indicator - Add test_multiperiod_time_warning and test_binary_time_no_multiperiod_warning - Update staggered test to also assert multi-period warning fires - Rename test_treatment_collinear_with_fe_raises_error to test_covariate_collinear_with_interaction_raises_error (matches actual behavior) - Update REGISTRY.md and METHODOLOGY_REVIEW.md to reflect changes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
/ai-review |
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment
Executive Summary
Methodology
Code Quality
Performance
Maintainability
Tech Debt
Security
Documentation/Tests
|
…fixtures
- Add elif block in TWFE.fit() warning when time has 2 unique values
not in {0,1} or {False,True} (ATT is correct, warning is advisory)
- Add 3 tests: non-binary time warning, boolean time no-warning, and
ATT/SE/p-value invariance to time encoding ({0,1} vs {2020,2021})
- Extract _run_r_feols_twfe to module level and cache R results in
session-scoped fixtures, reducing Rscript invocations from 6 to 2
- Update REGISTRY.md and METHODOLOGY_REVIEW.md edge case documentation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
/ai-review |
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall assessment: ✅ Looks goodExecutive summary
Methodology
Code Quality
Performance
Maintainability
Tech Debt
Security
Documentation/Tests
|
Summary
TwoWayFixedEffectsinteraction termD_i × Post_twas not being within-transformed before regression, producing incorrect ATT (~1/3 of true value) for multi-period panels with binarypostindicator. Fixed by applying within-transformation to the interaction term alongside outcome and covariates, matching R'sfixest::feols()behavior.tests/test_methodology_twfe.py) with 33 tests across 6 phasestest_twfe_with_absorbed_covariateto use correct TWFE specification after the bug fixMethodology references (required if estimator / math changes)
fixest::feols()behavior. By the Frisch-Waugh-Lovell theorem, all regressors must be projected out of the fixed effects space alongside the dependent variable.Validation
tests/test_methodology_twfe.py(33 new tests)tests/test_estimators.py(updatedtest_twfe_with_absorbed_covariate)fixest::feols(y ~ treated:post | unit + post, cluster=~unit)within 0.1%, SE within 1%Security / privacy
Generated with Claude Code