Skip to content

Commit 7c1e9d0

Browse files
authored
Merge pull request #434 from igerber/fix-audit-401-r2
Fix #401 holistic audit residuals: two stale docstrings around dCDH by_path / paths_of_interest
2 parents 917a786 + 0434408 commit 7c1e9d0

2 files changed

Lines changed: 31 additions & 13 deletions

File tree

diff_diff/chaisemartin_dhaultfoeuille.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,26 @@ def _validate_and_aggregate_to_cells(
143143
Raises
144144
------
145145
ValueError
146-
On missing columns, NaN treatment / outcome values, non-numeric
147-
treatment / outcome that cannot be coerced, or non-binary raw
148-
treatment values.
146+
On missing columns; NaN values in any of the ``group``, ``time``,
147+
``treatment``, or ``outcome`` columns (``group`` and ``time`` are
148+
rejected pre-``groupby`` because ``groupby`` silently drops NaN
149+
keys, which would change the estimation sample without warning);
150+
non-numeric treatment / outcome that cannot be coerced via
151+
``pd.to_numeric``; or within-cell-varying treatment (any
152+
``(group, time)`` cell where ``d_min != d_max``, since fuzzy DiD
153+
is out of scope and deferred to a separate dCdH 2018 paper).
154+
Integer-coded non-binary treatment (the ``by_path`` /
155+
``paths_of_interest`` requirement) is enforced separately at
156+
``fit()`` time, not here at aggregation time — this helper
157+
accepts continuous ``d_gt`` cell means and lets ``fit()`` decide
158+
whether the integer-only contract applies.
159+
160+
Under the survey-weighted path (``weights`` is not ``None``),
161+
zero-weight rows are pre-filtered before any NaN / coercion /
162+
within-cell validation per the ``SurveyDesign.subpopulation()``
163+
out-of-sample contract — invalid values in zero-weight rows
164+
therefore do NOT raise. NaN / coercion / within-cell checks
165+
still apply to all positive-weight rows.
149166
"""
150167
# 1. Required columns
151168
missing = [c for c in (outcome, group, time, treatment) if c not in data.columns]

diff_diff/chaisemartin_dhaultfoeuille_results.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -625,16 +625,17 @@ class ChaisemartinDHaultfoeuilleResults:
625625
)
626626
# Per-path joint sup-t simultaneous-band metadata. Keyed by path
627627
# tuple; each entry holds `{"crit_value", "alpha", "n_bootstrap",
628-
# "method", "n_valid_horizons"}`. Populated when `by_path` is a
629-
# positive int AND `n_bootstrap > 0`. The joint band itself is
630-
# written per-horizon as `cband_conf_int` on
631-
# `path_effects[path]["horizons"][l]` (mirrors the OVERALL
632-
# `event_study_effects[l]["cband_conf_int"]` pattern at
633-
# `chaisemartin_dhaultfoeuille.py:2865-2875`). Empty-state contract:
634-
# `None` when not requested (no bootstrap or `by_path is None`); `{}`
635-
# when requested but no path passed both gates (>=2 valid horizons
636-
# AND a strict majority — more than 50% — of finite sup-t draws).
637-
# The bands cover joint inference
628+
# "method", "n_valid_horizons"}`. Populated when EITHER `by_path` is
629+
# a positive int OR `paths_of_interest` is non-empty AND
630+
# `n_bootstrap > 0`. The joint band itself is written per-horizon as
631+
# `cband_conf_int` on `path_effects[path]["horizons"][l]` (mirrors
632+
# the OVERALL `event_study_effects[l]["cband_conf_int"]` pattern
633+
# populated alongside the bootstrap propagation in
634+
# `chaisemartin_dhaultfoeuille.py::fit`). Empty-state contract:
635+
# `None` when not requested (no bootstrap, or both `by_path` and
636+
# `paths_of_interest` are `None`); `{}` when requested but no path
637+
# passed both gates (>=2 valid horizons AND a strict majority — more
638+
# than 50% — of finite sup-t draws). The bands cover joint inference
638639
# WITHIN a single path across horizons; they do NOT provide
639640
# simultaneous coverage across paths.
640641
path_sup_t_bands: Optional[Dict[Tuple[int, ...], Dict[str, Any]]] = field(

0 commit comments

Comments
 (0)