Repository: scipy/scipy
File: scipy/stats/_binomtest.py (Python)

Code before:
        >>> result = binomtest(k=7, n=50, p=0.1)
        >>> result.statistic
        0.14
        >>> result.proportion_ci()
        ConfidenceInterval(low=0.05819170033997342, high=0.26739600249700846)
        """
        if method not in ('exact', 'wilson', 'wilsoncc'):
            raise ValueError(f"method ('{method}') must be one of 'exact', "
                             "'wilson' or 'wilsoncc'.")
        if not (0 <= confidence_level <= 1):
            raise ValueError(f'confidence_level ({confidence_level}) must be in '
                             'the interval [0, 1].')
        if method == 'exact':
            low, high = _binom_exact_conf_int(self.k, self.n,
                                              confidence_level,
                                              self.alternative)
        else:
            # method is 'wilson' or 'wilsoncc'
            low, high = _binom_wilson_conf_int(self.k, self.n,
                                               confidence_level,
                                               self.alternative,
                                               correction=method == 'wilsoncc')
        return ConfidenceInterval(low=low, high=high)


def _binom_exact_conf_int(k, n, confidence_level, alternative):
    """
    Compute the estimate and confidence interval for the binomial test.

    Returns proportion, prop_low, prop_high
    """
    init = (0.0, 1.0)
    args = (k, n)
    alpha = ((1 - confidence_level) / 2 if alternative == 'two-sided'
             else 1 - confidence_level)

    plow = (np.zeros(k.shape, dtype=np.float64) if alternative == 'less' else
            find_root(lambda p, k, n: binom.sf(k-1, n, p) - alpha, init, args=args).x)
    phigh = (np.ones(k.shape, dtype=np.float64) if alternative == 'greater' else
             find_root(lambda p, k, n: binom.cdf(k, n, p) - alpha, init, args=args).x)

    plow = np.where(k == 0, 0.0, plow)
    phigh = np.where(k == n, 1.0, phigh)
    return plow, phigh


def _binom_wilson_conf_int(k, n, confidence_level, alternative, correction):
    # This function assumes that the arguments have already been validated.
    # In particular, `alternative` must be one of 'two-sided', 'less' or
    # 'greater'.
    p = k / n

Review comment (suggestion):
`confidence_level` could easily be an array, if desired, but I don't suppose anyone is asking for it.

Code after:
        >>> result = binomtest(k=7, n=50, p=0.1)
        >>> result.statistic
        0.14
        >>> result.proportion_ci()
        ConfidenceInterval(low=0.05819170033997342, high=0.26739600249700846)
        """
        if method not in ('exact', 'wilson', 'wilsoncc'):
            raise ValueError(f"method ('{method}') must be one of 'exact', "
                             "'wilson' or 'wilsoncc'.")
        if not (0 <= confidence_level <= 1):
            raise ValueError(f'confidence_level ({confidence_level}) must be in '
                             'the interval [0, 1].')
        if method == 'exact':
            low, high = _binom_exact_conf_int(self.k, self.n,
                                              confidence_level,
                                              self.alternative)
        else:
            # method is 'wilson' or 'wilsoncc'
            low, high = _binom_wilson_conf_int(self.k, self.n,
                                               confidence_level,
                                               self.alternative,
                                               correction=method == 'wilsoncc')
        return ConfidenceInterval(low=low[()], high=high[()])


def _binom_exact_conf_int(k, n, confidence_level, alternative):
    """
    Compute the estimate and confidence interval for the binomial test.

    Returns proportion, prop_low, prop_high
    """
    init = (0.0, 1.0)
    args = (k, n)
    alpha = ((1 - confidence_level) / 2 if alternative == 'two-sided'
             else 1 - confidence_level)

    # I think using the private methods here is fine, since we will only evaluate with
    # valid `p`, `k`, and `n` (or all NaNs). One exception is when `k=0` and
    # `binom._sf(k-1, n, p)`: evaluates to NaN, but that's not a problem because
    # `plow` has a special case for `k=0` below.
    plow = (np.zeros(k.shape, dtype=np.float64) if alternative == 'less' else
            find_root(lambda p, k, n: binom._sf(k-1, n, p) - alpha, init, args=args).x)
    phigh = (np.ones(k.shape, dtype=np.float64) if alternative == 'greater' else
             find_root(lambda p, k, n: binom._cdf(k, n, p) - alpha, init, args=args).x)

    plow = np.where(k == 0, 0.0, plow)
    phigh = np.where(k == n, 1.0, phigh)
    return plow, phigh


def _binom_wilson_conf_int(k, n, confidence_level, alternative, correction):