Skip to content

Commit 49301cd

Browse files
authored
Merge pull request #560 from propcgamer20-png/fix/significance-confidence-affects-verdict
fix: significance_report's confidence parameter now affects the significant flag
2 parents ad0135b + 1371d56 commit 49301cd

2 files changed

Lines changed: 31 additions & 1 deletion

File tree

faircode/significance.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,15 @@ def permutation_test(group_a, group_b, n_permutations=10000, random_state=42):
9393
def significance_report(group_a, group_b, n_resamples=10000,
9494
n_permutations=10000, confidence=0.95,
9595
random_state=42):
96+
"""Bootstrap CI + permutation p-value for the gap mean(a) - mean(b).
97+
98+
`confidence` sets both the width of the returned CI *and* the
99+
significance threshold: `significant` is `p_value < (1 - confidence)`.
100+
At the default `confidence=0.95` that is the usual `p < 0.05`; a caller
101+
passing `confidence=0.99` gets the correspondingly stricter `p < 0.01`,
102+
so the CI and the verdict move together instead of the verdict being
103+
pinned at 0.05 regardless.
104+
"""
96105
a = _as_array(group_a)
97106
b = _as_array(group_b)
98107
gap, ci_low, ci_high = bootstrap_ci(a, b, n_resamples, confidence,
@@ -105,7 +114,7 @@ def significance_report(group_a, group_b, n_resamples=10000,
105114
"ci_low": ci_low,
106115
"ci_high": ci_high,
107116
"p_value": p_value,
108-
"significant": p_value < 0.05,
117+
"significant": p_value < (1.0 - confidence),
109118
"n_a": n_a,
110119
"n_b": n_b,
111120
"small_sample_warning": n_a < 30 or n_b < 30,

tests/test_significance.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,27 @@ def test_separated_groups_are_significant_and_ci_excludes_zero():
3737
assert rep["ci_low"] <= rep["gap"] <= rep["ci_high"]
3838

3939

40+
def test_confidence_tightens_the_significance_threshold_not_just_the_ci():
41+
# A gap with 0.01 < p < 0.05 is significant at the default confidence
42+
# (0.95 -> p < 0.05) but not at confidence=0.99 (-> p < 0.01). Before
43+
# #548 the `significant` flag was pinned to p < 0.05 regardless of
44+
# `confidence`, which only widened/narrowed the CI.
45+
rng = np.random.default_rng(0)
46+
for _ in range(5):
47+
a = rng.binomial(1, 0.55, size=60).astype(float)
48+
b = rng.binomial(1, 0.35, size=60).astype(float)
49+
50+
r95 = significance_report(a, b, n_resamples=3000, n_permutations=3000,
51+
confidence=0.95, random_state=4)
52+
r99 = significance_report(a, b, n_resamples=3000, n_permutations=3000,
53+
confidence=0.99, random_state=4)
54+
55+
assert r95["p_value"] == r99["p_value"] # same permutation test
56+
assert 0.01 < r95["p_value"] < 0.05
57+
assert r95["significant"] is True
58+
assert r99["significant"] is False
59+
60+
4061
# ── Determinism ──────────────────────────────────────────────────────────────
4162
def test_random_state_makes_results_deterministic():
4263
a = [1] * 40 + [0] * 60

0 commit comments

Comments
 (0)