Skip to content

Commit 3824de8

Browse files
igerberclaude
andcommitted
Round 11: summary() footer branches on inference mode
P2 fix: summary() was unconditionally printing "dCDH analytical CI is conservative under Assumption 8" even when n_bootstrap > 0 and the displayed p_value / conf_int were bootstrap-based. The footer now branches on bootstrap_results: when bootstrap is active, it prints "p-value and CI are multiplier-bootstrap percentile inference (N iterations, weight_type weights)"; when analytical, it keeps the original conservative-CI note. Added test assertions pinning both paths: - test_summary_formats_without_error (analytical mode): asserts "analytical CI is conservative" is present and "multiplier- bootstrap" is absent - test_bootstrap_p_value_and_ci_propagated_to_top_level (bootstrap mode): asserts "multiplier-bootstrap percentile inference" is present and "analytical CI is conservative" is absent 111 tests still pass; black, ruff clean. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 819ba57 commit 3824de8

2 files changed

Lines changed: 20 additions & 4 deletions

File tree

diff_diff/chaisemartin_dhaultfoeuille_results.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -520,10 +520,18 @@ def summary(self, alpha: Optional[float] = None) -> str:
520520
lines.append(f"{'CV (SE/|DID_M|):':<25} {cv:>10.4f}")
521521

522522
lines.append("")
523-
lines.append(
524-
"Note: dCDH analytical CI is conservative under Assumption 8" " (independent groups);"
525-
)
526-
lines.append(" exact under iid sampling.")
523+
if self.bootstrap_results is not None:
524+
lines.append("Note: p-value and CI are multiplier-bootstrap percentile inference")
525+
lines.append(
526+
f" ({self.bootstrap_results.n_bootstrap} iterations, "
527+
f"{self.bootstrap_results.weight_type} weights)."
528+
)
529+
else:
530+
lines.append(
531+
"Note: dCDH analytical CI is conservative under Assumption 8"
532+
" (independent groups);"
533+
)
534+
lines.append(" exact under iid sampling.")
527535
lines.append("")
528536

529537
# --- Joiners and leavers ---

tests/test_chaisemartin_dhaultfoeuille.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,6 +1043,11 @@ def test_bootstrap_p_value_and_ci_propagated_to_top_level(self, data, ci_params)
10431043
# the bootstrap output.
10441044
summary_text = results.summary()
10451045
assert "DID_M" in summary_text
1046+
# The summary footer should mention bootstrap inference, NOT
1047+
# the analytical-CI conservativeness note (which only applies
1048+
# when n_bootstrap=0). This pins the P2 fix from Round 11.
1049+
assert "multiplier-bootstrap percentile inference" in summary_text
1050+
assert "analytical CI is conservative" not in summary_text
10461051
df_overall = results.to_dataframe(level="overall")
10471052
assert df_overall.iloc[0]["p_value"] == pytest.approx(br.overall_p_value)
10481053
assert df_overall.iloc[0]["conf_int_lower"] == pytest.approx(br.overall_ci[0])
@@ -1090,6 +1095,9 @@ def test_summary_formats_without_error(self, results):
10901095
assert "DID_M" in out
10911096
assert "DID_+" in out
10921097
assert "DID_-" in out
1098+
# Analytical mode (n_bootstrap=0) shows the conservative-CI note
1099+
assert "analytical CI is conservative" in out
1100+
assert "multiplier-bootstrap" not in out
10931101

10941102
def test_print_summary(self, results, capsys):
10951103
results.print_summary()

0 commit comments

Comments
 (0)