Skip to content

Commit d682bf4

Browse files
igerberclaude
andcommitted
Zero aweight scores for zero-weight rows, fix self.df_ effective count
Fix aweight HC1/clustered path: zero out score rows where weights==0 so zero-weight observations don't contribute to the sandwich meat (mirrors the TSL survey vcov implementation). Fix LinearRegression.df_: use positive-weight count for pweight/aweight with zeros, matching compute_robust_vcov effective-n rule. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c6c2c38 commit d682bf4

1 file changed

Lines changed: 10 additions & 3 deletions

File tree

diff_diff/linalg.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,9 @@ def _compute_robust_vcov_numpy(
10641064
scores = X * (weights * residuals)[:, np.newaxis]
10651065
else:
10661066
scores = X * residuals[:, np.newaxis]
1067+
# Zero out scores for zero-weight aweight rows (subpopulation invariance)
1068+
if weights is not None and np.any(weights == 0):
1069+
scores[weights == 0] = 0.0
10671070

10681071
if cluster_ids is None:
10691072
# HC1 (heteroskedasticity-robust) standard errors
@@ -1870,10 +1873,14 @@ def fit(
18701873
# This is needed for correct degrees of freedom in inference
18711874
nan_mask = np.isnan(coefficients)
18721875
self.n_params_effective_ = int(self.n_params_ - np.sum(nan_mask))
1873-
# For fweights, df uses sum(w) - k (effective sample size)
1876+
# Effective n for df: fweights use sum(w), pweight/aweight with
1877+
# zeros use positive-weight count (matches compute_robust_vcov)
18741878
n_eff_df = self.n_obs_
1875-
if self.weights is not None and self.weight_type == "fweight":
1876-
n_eff_df = int(round(np.sum(self.weights)))
1879+
if self.weights is not None:
1880+
if self.weight_type == "fweight":
1881+
n_eff_df = int(round(np.sum(self.weights)))
1882+
elif np.any(self.weights == 0):
1883+
n_eff_df = int(np.count_nonzero(self.weights > 0))
18771884
self.df_ = n_eff_df - self.n_params_effective_ - df_adjustment
18781885

18791886
# Survey degrees of freedom: n_PSU - n_strata (overrides standard df)

0 commit comments

Comments
 (0)