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

Code before:
    ssq = xp.concat(ssq, axis=0)
    dtype = Ni.dtype
    Ntot = xp.sum(Ni, axis=0)
    spsq = xp.sum((Ni - 1)*ssq, axis=0, dtype=dtype) / (Ntot - k)
    numer = ((Ntot - k) * xp.log(spsq)
             - xp.sum((Ni - 1)*xp.log(ssq), axis=0, dtype=dtype))
    denom = (1 + 1/(3*(k - 1))
             * ((xp.sum(1/(Ni - 1), axis=0)) - 1/(Ntot - k)))
    T = numer / denom

    chi2 = _SimpleChi2(xp.asarray(k-1, dtype=dtype, device=xp_device(T)))
    pvalue = _get_pvalue(T, chi2, alternative='greater', symmetric=False, xp=xp)

    T = xp.clip(T, min=0., max=xp.inf)
    T = T[()] if T.ndim == 0 else T
    pvalue = pvalue[()] if pvalue.ndim == 0 else pvalue

    return BartlettResult(T, pvalue)


LeveneResult = namedtuple('LeveneResult', ('statistic', 'pvalue'))


@xp_capabilities(cpu_only=True, exceptions=['cupy'],
                 jax_jit=False,  # needs fdtrc
                 extra_note="Option `center='trimmed' is incompatible with MArray."
                 )
@_axis_nan_policy_factory(LeveneResult, n_samples=None)
def levene(*samples, center='median', proportiontocut=0.05, axis=0):
    r"""Perform Levene test for equal variances.

    The Levene test tests the null hypothesis that all input samples
    are from populations with equal variances.  Levene's test is an
    alternative to Bartlett's test `bartlett` in the case where
    there are significant deviations from normality.

    Parameters
    ----------
    sample1, sample2, ... : array_like
        The sample data, possibly with different lengths.
    center : {'mean', 'median', 'trimmed'}, optional
        Which statistics to use to center data points within each sample.  Default
        is 'median'.
    proportiontocut : float, optional
        When `center` is 'trimmed', this gives the proportion of data points
        to cut from each end. (See `scipy.stats.trim_mean`.)
        Default is 0.05.
    axis : int or tuple of ints, default: 0
        If an int or tuple of ints, the axis or axes of the input along which
        to compute the statistic. The statistic of each axis-slice (e.g. row)
        of the input will appear in a corresponding element of the output.

Review comment (suggestion):
```suggestion
                 extra_note="Option ``center='trimmed'`` is incompatible with MArray."
```

Code after:
    ([3]_).

    References
    ----------
    .. [1]  https://www.itl.nist.gov/div898/handbook/eda/section3/eda357.htm
    .. [2]  Snedecor, George W. and Cochran, William G. (1989), Statistical
              Methods, Eighth Edition, Iowa State University Press.
    .. [3] Park, C. and Lindsay, B. G. (1999). Robust Scale Estimation and
           Hypothesis Testing based on Quadratic Inference Function. Technical
           Report #99-03, Center for Likelihood Studies, Pennsylvania State
           University.
    .. [4] Bartlett, M. S. (1937). Properties of Sufficiency and Statistical
           Tests. Proceedings of the Royal Society of London. Series A,
           Mathematical and Physical Sciences, Vol. 160, No.901, pp. 268-282.

    Examples
    --------

    Test whether the lists `a`, `b` and `c` come from populations
    with equal variances.

    >>> import numpy as np
    >>> from scipy import stats
    >>> a = [8.88, 9.12, 9.04, 8.98, 9.00, 9.08, 9.01, 8.85, 9.06, 8.99]
    >>> b = [8.88, 8.95, 9.29, 9.44, 9.15, 9.58, 8.36, 9.18, 8.67, 9.05]
    >>> c = [8.95, 9.12, 8.95, 8.85, 9.03, 8.84, 9.07, 8.98, 8.86, 8.98]
    >>> stat, p = stats.bartlett(a, b, c)
    >>> p
    1.1254782518834628e-05

    The very small p-value suggests that the populations do not have equal
    variances.

    This is not surprising, given that the sample variance of `b` is much
    larger than that of `a` and `c`:

    >>> [np.var(x, ddof=1) for x in [a, b, c]]
    [0.007054444444444413, 0.13073888888888888, 0.008890000000000002]

    For a more detailed example, see :ref:`hypothesis_bartlett`.
    """
    xp = array_namespace(*samples)

    k = len(samples)
    if k < 2:
        raise ValueError("Must enter at least two input sample vectors.")

    if axis is None:
        samples = [xp_ravel(sample) for sample in samples]
    else:
        samples = _broadcast_arrays(samples, axis=axis, xp=xp)