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

Code before:
    As we can see, the p-value is indeed quite low. Use of
    ``alternative='less'`` should thus yield a large p-value:

    >>> ansari(x1, x3, alternative='less')
    AnsariResult(statistic=425.0, pvalue=0.9998643258449039)

    """
    if alternative not in {'two-sided', 'greater', 'less'}:
        raise ValueError("'alternative' must be 'two-sided',"
                         " 'greater', or 'less'.")

    if not hasattr(_abw_state, 'a'):
        _abw_state.a = _ABW()

    # _axis_nan_policy decorator guarantees that axis=-1
    n = x.shape[-1]
    m = y.shape[-1]
    if m < 1:  # needed by test_axis_nan_policy; not user-facing
        raise ValueError("Not enough other observations.")
    if n < 1:
        raise ValueError("Not enough test observations.")

    N = m + n
    xy = np.concatenate([x, y], axis=-1)  # combine
    rank, t = _stats_py._rankdata(xy, method='average', return_ties=True)
    symrank = np.min(np.stack((rank, N - rank + 1), axis=0), axis=0)
    AB = np.sum(symrank[..., :n], axis=-1)
    repeats = np.any(t > 1)  # in theory we could branch for each slice separately
    exact = ((m < 55) and (n < 55) and not repeats)
    if exact:
        cdf = np.vectorize(_abw_state.a.cdf, otypes=[np.float64])
        sf = np.vectorize(_abw_state.a.sf, otypes=[np.float64])
        if alternative == 'two-sided':
            pval = 2.0 * np.minimum(cdf(AB, n, m),
                                    sf(AB, n, m))
        elif alternative == 'greater':
            # AB statistic is _smaller_ when ratio of scales is larger,
            # so this is the opposite of the usual calculation
            pval = cdf(AB, n, m)
        else:
            pval = sf(AB, n, m)
        return AnsariResult(AB, np.minimum(1.0, pval))

    # otherwise compute normal approximation
    if N % 2:  # N odd
        mnAB = n * (N+1.0)**2 / 4.0 / N
        varAB = n * m * (N+1.0) * (3+N**2) / (48.0 * N**2)
    else:
        mnAB = n * (N+2.0) / 4.0
        varAB = m * n * (N+2) * (N-2.0) / 48 / (N-1.0)
    if repeats:   # adjust variance estimates

Review comment (suggestion):
```suggestion
    symrank = np.minimum(rank, N - rank + 1)
```

Code after:
    >>> x2 = rng.normal(loc=0, scale=2, size=25)
    >>> x3 = rng.normal(loc=0, scale=1.25, size=25)

    First we apply `ansari` to `x1` and `x2`.  These samples are drawn
    from the same distribution, so we expect the Ansari-Bradley test
    should not lead us to conclude that the scales of the distributions
    are different.

    >>> ansari(x1, x2)
    AnsariResult(statistic=541.0, pvalue=0.9762532927399098)

    With a p-value close to 1, we cannot conclude that there is a
    significant difference in the scales (as expected).

    Now apply the test to `x1` and `x3`:

    >>> ansari(x1, x3)
    AnsariResult(statistic=425.0, pvalue=0.0003087020407974518)

    The probability of observing such an extreme value of the statistic
    under the null hypothesis of equal scales is only 0.03087%. We take this
    as evidence against the null hypothesis in favor of the alternative:
    the scales of the distributions from which the samples were drawn
    are not equal.

    We can use the `alternative` parameter to perform a one-tailed test.
    In the above example, the scale of `x1` is greater than `x3` and so
    the ratio of scales of `x1` and `x3` is greater than 1. This means
    that the p-value when ``alternative='greater'`` should be near 0 and
    hence we should be able to reject the null hypothesis:

    >>> ansari(x1, x3, alternative='greater')
    AnsariResult(statistic=425.0, pvalue=0.0001543510203987259)

    As we can see, the p-value is indeed quite low. Use of
    ``alternative='less'`` should thus yield a large p-value:

    >>> ansari(x1, x3, alternative='less')
    AnsariResult(statistic=425.0, pvalue=0.9998643258449039)

    """
    if alternative not in {'two-sided', 'greater', 'less'}:
        raise ValueError("'alternative' must be 'two-sided',"
                         " 'greater', or 'less'.")

    if not hasattr(_abw_state, 'a'):
        _abw_state.a = _ABW()

    # _axis_nan_policy decorator guarantees that axis=-1
    n = x.shape[-1]
    m = y.shape[-1]