Skip to content

Commit 150c9c0

Browse files
igerberclaude
andcommitted
Reject replicate designs in TwoWayFixedEffects, fix compute_deff gate
TWFE performs weighted within-transformation once with full-sample weights, then lets LinearRegression compute replicate variance on the frozen transformed design. This is methodologically incorrect — replicate variance requires recomputing the within-transform per replicate (same reason as SunAbraham rejection). Also fix compute_deff() to gate on survey design presence instead of survey_df_, allowing DEFF computation even when replicate df is undefined. Fix REGISTRY fweight note consistency (non-negative, not positive). Update replicate support matrix to include TWFE rejection. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 10bfc03 commit 150c9c0

3 files changed

Lines changed: 19 additions & 9 deletions

File tree

diff_diff/linalg.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1885,7 +1885,7 @@ def compute_deff(self, coefficient_names=None):
18851885
DEFFDiagnostics
18861886
"""
18871887
self._check_fitted()
1888-
if self.survey_df_ is None:
1888+
if not (hasattr(self, 'survey_design') and self.survey_design is not None):
18891889
raise ValueError(
18901890
"compute_deff() requires a survey design. "
18911891
"Fit with survey_design= first."

diff_diff/twfe.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,16 @@ def fit( # type: ignore[override]
127127
resolved_survey, survey_weights, survey_weight_type, survey_metadata = (
128128
_resolve_survey_for_fit(survey_design, data, self.inference)
129129
)
130+
# Reject replicate-weight designs — TWFE within-transformation must
131+
# be recomputed per replicate (same reason as SunAbraham rejection)
132+
if resolved_survey is not None and resolved_survey.uses_replicate_variance:
133+
raise NotImplementedError(
134+
"TwoWayFixedEffects does not yet support replicate-weight "
135+
"survey designs. The weighted within-transformation must be "
136+
"recomputed for each replicate. Use CallawaySantAnna or "
137+
"TripleDifference for replicate-weight inference, or use a "
138+
"TSL-based survey design (strata/psu/fpc)."
139+
)
130140

131141
# Use unit-level clustering if not specified (use local variable to avoid mutation)
132142
cluster_var = self.cluster if self.cluster is not None else unit

docs/methodology/REGISTRY.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1907,9 +1907,9 @@ unequal selection probabilities).
19071907
- **Note:** pweight HC1 meat uses score outer products (Σ s_i s_i' where
19081908
s_i = w_i x_i u_i), giving w² in the meat. fweight HC1 meat uses
19091909
X'diag(w u²)X (one power of w), matching frequency-expanded HC1.
1910-
- **Note:** fweights must be positive integers; fractional values are
1911-
rejected by `_validate_weights()`. This matches Stata's convention and
1912-
avoids ambiguous frequency semantics.
1910+
- **Note:** fweights must be non-negative integers; fractional values are
1911+
rejected by `_validate_weights()`. All-zero vectors rejected at solver
1912+
level. This matches Stata's convention.
19131913

19141914
### Absorbed Fixed Effects with Survey Weights
19151915

@@ -2049,11 +2049,11 @@ variance from the distribution of replicate estimates.
20492049
- **Supported**: CallawaySantAnna (reg, no bootstrap), ContinuousDiD
20502050
(no bootstrap), EfficientDiD (no bootstrap), TripleDifference (all
20512051
methods), LinearRegression (OLS path)
2052-
- **Rejected with NotImplementedError**: SunAbraham (within-transformation
2053-
must be recomputed per replicate), DifferenceInDifferences,
2054-
MultiPeriodDiD, StackedDiD (use compute_survey_vcov directly),
2055-
ImputationDiD, TwoStageDiD (custom variance), SyntheticDiD, TROP
2056-
(bootstrap-based variance)
2052+
- **Rejected with NotImplementedError**: SunAbraham, TwoWayFixedEffects
2053+
(within-transformation must be recomputed per replicate),
2054+
DifferenceInDifferences, MultiPeriodDiD, StackedDiD (use
2055+
compute_survey_vcov directly), ImputationDiD, TwoStageDiD (custom
2056+
variance), SyntheticDiD, TROP (bootstrap-based variance)
20572057
- CS/ContinuousDiD/EfficientDiD reject replicate + `n_bootstrap > 0`
20582058
(replicate weights provide analytical variance)
20592059
- **Note:** When invalid replicates are dropped in `compute_replicate_vcov`

0 commit comments

Comments
 (0)