Skip to content

Commit 4c8f630

Browse files
burningcostclaude
andcommitted
Fix ranking_ci zero-division when comparing a feature to itself
Two fixes from dependency audit: 1. _inference.py: guard in ranking_ci() when both arguments name the same feature. diff==0 and SE==0 (rho_a - rho_b is the zero vector), so 0/0 produced z_stat=inf. Return z_stat=0.0, p_value=1.0 in this case — the null of equal importance trivially holds when comparing a feature against itself. 2. test_inference.py: test_wrong_feature_names_length_raises was matching against "n_features" which no longer appears in the ValueError message. Updated regex to match the actual message "len(feature_names)=...". Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent ad0fef5 commit 4c8f630

2 files changed

Lines changed: 10 additions & 5 deletions

File tree

src/shap_relativities/_inference.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -579,10 +579,15 @@ def ranking_ci(self, feature_a: str, feature_b: str) -> dict[str, float]:
579579
se_diff = float(np.sqrt(max(var_diff, 0.0)))
580580

581581
diff = theta_a - theta_b
582-
z_stat = diff / se_diff if se_diff > 0 else float("inf")
583-
584-
# One-sided p-value for H1: theta_a > theta_b
585-
p_value = float(1.0 - stats.norm.cdf(z_stat))
582+
# Guard: when both feature arguments are identical, diff==0 and SE==0.
583+
# 0/0 is indeterminate; the correct result is z_stat=0, p_value=1.
584+
if diff == 0.0 and se_diff == 0.0:
585+
z_stat = 0.0
586+
p_value = 1.0
587+
else:
588+
z_stat = diff / se_diff if se_diff > 0 else float("inf")
589+
# One-sided p-value for H1: theta_a > theta_b
590+
p_value = float(1.0 - stats.norm.cdf(z_stat))
586591

587592
# Two-sided CI on the difference
588593
z_ci = float(stats.norm.ppf((1 + self.ci_level) / 2))

tests/test_inference.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ def test_mismatched_shapes_raises(self):
336336
SHAPInference(np.ones((100, 2)), np.ones(99), ["a", "b"])
337337

338338
def test_wrong_feature_names_length_raises(self):
339-
with pytest.raises(ValueError, match="n_features"):
339+
with pytest.raises(ValueError, match="len\(feature_names\)"):
340340
SHAPInference(np.ones((100, 2)), np.ones(100), ["a"])
341341

342342
def test_1d_shap_raises(self):

0 commit comments

Comments
 (0)