Skip to content

Commit cb835e3

Browse files
igerberclaude
andcommitted
test+docs(two_stage): CI-review P1 - methodology suite asserted the old lstsq warning
tests/test_methodology_two_stage.py::test_singular_omega0_warns_and_falls_back still matched "lstsq" in the fallback warning (my sibling sweep covered tests/test_two_stage.py but missed the methodology file); now matches "falling back to sparse LSMR". Also the stale spillover.py re-factorization note describing the removed dense toarray() fallback (review P3). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Lbd6nqWmg4snvvBmegwqiw
1 parent 89fd43c commit cb835e3

2 files changed

Lines changed: 6 additions & 7 deletions

File tree

diff_diff/spillover.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,9 +1597,8 @@ def _build_butts_fe_design_csr(
15971597
supported warn-and-drop fit), the input code arrays can be sparse —
15981598
e.g. ``unit_codes = [0, 1, 3, 4]`` with code 2 dropped. Building
15991599
``X_10`` on the raw codes would materialize an all-zero FE column at
1600-
index 2, forcing ``sparse_factorized`` onto the dense
1601-
``lstsq``/``XtX_10.toarray()`` fallback unnecessarily (large-memory
1602-
path on big panels). To avoid this, re-factorize via
1600+
index 2, forcing ``sparse_factorized`` onto the certified sparse-LSMR
1601+
fallback unnecessarily (a warned degraded path). To avoid this, re-factorize via
16031602
:func:`pd.factorize` on entry to compact the code space to
16041603
``0..n_unique-1`` (no-op when codes are already contiguous; mirrors
16051604
the column-space convention of ``TwoStageDiD._build_fe_design``).

tests/test_methodology_two_stage.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -409,8 +409,8 @@ def test_singular_omega0_warns_and_falls_back(self) -> None:
409409
"""A rank-deficient Stage-1 design (a period observed only among treated
410410
obs -> its time FE is unidentified in Omega_0 -> X_10'X_10 singular) makes
411411
the sparse factorization in the GMM variance fail; the code must emit a
412-
UserWarning and route to the dense lstsq fallback, still returning a
413-
finite SE."""
412+
UserWarning and route to the certified sparse-LSMR fallback, still
413+
returning a finite SE."""
414414
rng = np.random.default_rng(_BASE_SEED_VAR + 9)
415415
rows: List[Dict[str, Any]] = []
416416
uid = 0
@@ -432,8 +432,8 @@ def test_singular_omega0_warns_and_falls_back(self) -> None:
432432
panel, outcome="outcome", unit="unit", time="time", first_treat="first_treat"
433433
)
434434
assert any(
435-
"lstsq" in str(w.message) for w in caught
436-
), "expected the dense-lstsq fallback warning under a singular Omega_0"
435+
"falling back to sparse LSMR" in str(w.message) for w in caught
436+
), "expected the sparse-LSMR fallback warning under a singular Omega_0"
437437
assert np.isfinite(res.overall_se)
438438

439439
def test_bootstrap_scores_use_exact_residuals(self) -> None:

0 commit comments

Comments
 (0)