Sitelet https://github.com/statsmodels/statsmodels/pull/10399
Skip to content

BUG: reject alpha outside (0, 1) in Table2x2 confint methods - #10399

Merged
bashtage merged 2 commits into
statsmodels:mainfrom
simpleqt:sq/table2x2-confint-alpha
Oct 4, 2026
Merged

bashtage merged 2 commits into
statsmodels:mainfrom
simpleqt:sq/table2x2-confint-alpha

Conversation

@simpleqt

@simpleqt simpleqt commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Problem

The `Table2x2` confidence-interval methods silently accept `alpha` outside (0, 1):

>>> t2 = Table2x2(np.array([[10., 5.], [8., 12.]]))
>>> t2.oddsratio_confint(alpha=2)
(inf, 0.0)    # silent

`log_oddsratio_confint` computes `f = -stats.norm.ppf(alpha / 2)`, which is `-inf` for `alpha = 2` and `nan` for `alpha = 0`; `np.exp` turns that into `inf`/`0` bounds. `log_riskratio_confint` has the identical pattern.

Fix

Raise `ValueError` (`alpha must be in the range (0, 1)`) after the `method` validation in both `log_oddsratio_confint` and `log_riskratio_confint`. The public wrappers `oddsratio_confint` and `riskratio_confint` delegate to them, so all four entry points are covered.

Tests

Added `test_table2x2_confint_invalid_alpha_raises` in `statsmodels/stats/tests/test_contingency_tables.py` covering all four methods (`alpha=2` and `alpha=0`) plus a finite sanity check. Verified red without the fix and green with it; the full test module passes (90 passed) and the diff introduces no new `ruff check` findings.

AI Disclosure

Contributions comply with the statsmodels AI Policy. Completed option:

  • No AI tools were used to develop this pull request.
  • AI tools were used.
    Tool(s): `ZCode (GLM-based coding agent)`.
    Used for: `drafting the repro script, the implementation, the tests, and the PR text; I executed all code locally, verified the red/green test cycle, and reviewed every line of the diff`.
    I have personally read, understood, and can explain every line of this diff, and
    have verified the statistical/numerical correctness of the change.

Table2x2.log_oddsratio_confint and log_riskratio_confint silently
accepted alpha outside (0, 1): stats.norm.ppf(alpha / 2) degenerates and
oddsratio_confint returned (inf, 0.0). Raise ValueError; the exp-based
oddsratio/riskratio confint wrappers delegate and are covered
transitively.
Copilot AI balanced review requested due to automatic review settings October 3, 2026 17:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@bashtage
bashtage merged commit a5ff5c4 into statsmodels:main Oct 4, 2026
13 checks passed
@bashtage

bashtage commented Oct 4, 2026

Copy link
Copy Markdown
Member

Thanks.

bashtage added a commit that referenced this pull request Oct 5, 2026
The checks added in GH-10379, GH-10386, GH-10388, GH-10392, GH-10393,
GH-10399, GH-10405, GH-10406, GH-10411, GH-10420, GH-10421, GH-10423,
GH-10425, GH-10426 and GH-10431 compare the arguments with scalars,
for example `if not 0 < alpha < 1`, `if low > upp` or `if dispersion < 0`.
These raise "The truth value of an array with more than one element is
ambiguous" for arrays and Series. The functions broadcast over these
arguments and return the same values as the calls for the elements in
0.15.0, for example a confidence interval for several alpha, the power
for several equivalence margins or a table of sample sizes.

Test with np.all and the comparison ufuncs instead, which work for
scalars, lists, arrays and Series, and which also reject NaN. The
error messages are unchanged. A new test checks for 50 arguments that an
array of two valid values gives the same result as the two calls with the
scalars, and that one invalid element (including NaN) is rejected.

Follow-up to GH-10379, GH-10386, GH-10388, GH-10392, GH-10393, GH-10399,
GH-10405, GH-10406, GH-10411, GH-10420, GH-10421, GH-10423, GH-10425,
GH-10426, GH-10431

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
bashtage added a commit that referenced this pull request Oct 5, 2026
The arguments that broadcast are documented as float or int, but arrays
work, and the previous commit keeps them working. Document them as
float or array_like in the functions of the previous commit and in
chisquare_power, which says in its Notes that it works vectorized.

Follow-up to GH-10379, GH-10386, GH-10388, GH-10392, GH-10393, GH-10399,
GH-10405, GH-10406, GH-10411, GH-10420, GH-10421, GH-10423, GH-10425,
GH-10426, GH-10431

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants