Commit 0040bad
Address PR #353 CI review round 3 (1 P1 + 1 P3)
P1 - row-level non-negative-dose guard in `_aggregate_for_joint_test`:
On a 2-period direct call to `joint_pretrends_test` or
`joint_homogeneity_test`, the n_periods < 3 path skips
`_validate_had_panel_event_study` (which requires >= 3 periods) and
falls through to `_aggregate_for_joint_test`. That helper collapsed
unit dose via `groupby(unit_col)[dose_col].max()`, which silently
recodes a negative post dose to 0 (`max(0, -d) = 0` for positive
pre-period d), allowing finite joint-Stute output on data that
violates the HAD support restriction `D_{g,t} >= 0` (paper Section 2).
Fix: add a row-level `dose_col >= 0` check in
`_aggregate_for_joint_test` BEFORE the groupby/max collapse.
Centralizes the guard so both data-in wrappers inherit it on the
n_periods < 3 fallback path. The multi-period path already enforces
the same invariant via `_validate_had_panel_event_study`, so the
contract is consistent across both wrapper dispatch modes.
P3 - regression test: new
`TestJointHomogeneityTest::test_two_period_negative_post_dose_raises`
constructs a 2-period panel with a single unit carrying a negative
post dose and asserts the wrapper raises `ValueError` with the
"negative dose value" substring rather than producing a finite
statistic via the groupby-max collapse.
124 tests pass (123 + 1 new R3 regression); black/ruff/mypy clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 84835de commit 0040bad
2 files changed
Lines changed: 59 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1737 | 1737 | | |
1738 | 1738 | | |
1739 | 1739 | | |
| 1740 | + | |
| 1741 | + | |
| 1742 | + | |
| 1743 | + | |
| 1744 | + | |
| 1745 | + | |
| 1746 | + | |
| 1747 | + | |
| 1748 | + | |
| 1749 | + | |
| 1750 | + | |
| 1751 | + | |
| 1752 | + | |
| 1753 | + | |
| 1754 | + | |
| 1755 | + | |
| 1756 | + | |
| 1757 | + | |
| 1758 | + | |
| 1759 | + | |
1740 | 1760 | | |
1741 | 1761 | | |
1742 | 1762 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2035 | 2035 | | |
2036 | 2036 | | |
2037 | 2037 | | |
| 2038 | + | |
| 2039 | + | |
| 2040 | + | |
| 2041 | + | |
| 2042 | + | |
| 2043 | + | |
| 2044 | + | |
| 2045 | + | |
| 2046 | + | |
| 2047 | + | |
| 2048 | + | |
| 2049 | + | |
| 2050 | + | |
| 2051 | + | |
| 2052 | + | |
| 2053 | + | |
| 2054 | + | |
| 2055 | + | |
| 2056 | + | |
| 2057 | + | |
| 2058 | + | |
| 2059 | + | |
| 2060 | + | |
| 2061 | + | |
| 2062 | + | |
| 2063 | + | |
| 2064 | + | |
| 2065 | + | |
| 2066 | + | |
| 2067 | + | |
| 2068 | + | |
| 2069 | + | |
| 2070 | + | |
| 2071 | + | |
| 2072 | + | |
| 2073 | + | |
| 2074 | + | |
| 2075 | + | |
| 2076 | + | |
2038 | 2077 | | |
2039 | 2078 | | |
2040 | 2079 | | |
| |||
0 commit comments