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

Code before:
    # compute Zij's
    Zijs = [xp.abs(sample - Yc) for sample, Yc in zip(samples, Ycis)]

    # compute Zbari
    Zbaris = [xp.mean(Zij, axis=-1, keepdims=True) for Zij in Zijs]
    Zbar = sum(Ni*Zbari for Ni, Zbari in zip(Nis, Zbaris)) / Ntot

    # compute numerator and denominator
    dfd = (Ntot - k)
    numer = dfd * sum(Ni * (Zbari - Zbar)**2
                      for Ni, Zbari in zip(Nis, Zbaris))
    dfn = (k - 1.0)
    denom = dfn * sum(xp.sum((Zij - Zbari)**2, axis=-1, keepdims=True)
                      for Zij, Zbari in zip(Zijs, Zbaris))

    W = numer / denom
    W = xp.squeeze(W, axis=-1)
    dfn, dfd = xp.asarray(dfn, dtype=W.dtype), xp.asarray(dfd, dtype=W.dtype)
    pval = _get_pvalue(W, _SimpleF(dfn, dfd), 'greater', xp=xp)
    return LeveneResult(W[()], pval[()])


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


@xp_capabilities(skip_backends=[('dask.array', 'no rankdata')], jax_jit=False)
@_axis_nan_policy_factory(FlignerResult, n_samples=None)
def fligner(*samples, center='median', proportiontocut=0.05, axis=0):
    r"""Perform Fligner-Killeen test for equality of variance.

    Fligner's test tests the null hypothesis that all input samples
    are from populations with equal variances.  Fligner-Killeen's test is
    distribution free when populations are identical [2]_.

    Parameters
    ----------
    sample1, sample2, ... : array_like
        Arrays of sample data.  Need not be the same length.
    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.
        If ``None``, the input will be raveled before computing the statistic.


Review comment (suggestion):
```suggestion
@xp_capabilities(skip_backends=[('dask.array', 'no rankdata'),
                                ('cupy', 'no rankdata')], jax_jit=False)
```

Code after:
    # compute Zij's
    Zijs = [xp.abs(sample - Yc) for sample, Yc in zip(samples, Ycis)]

    # compute Zbari
    Zbaris = [xp.mean(Zij, axis=-1, keepdims=True) for Zij in Zijs]
    Zbar = sum(Ni*Zbari for Ni, Zbari in zip(Nis, Zbaris)) / Ntot

    # compute numerator and denominator
    dfd = (Ntot - k)
    numer = dfd * sum(Ni * (Zbari - Zbar)**2
                      for Ni, Zbari in zip(Nis, Zbaris))
    dfn = (k - 1.0)
    denom = dfn * sum(xp.sum((Zij - Zbari)**2, axis=-1, keepdims=True)
                      for Zij, Zbari in zip(Zijs, Zbaris))

    W = numer / denom
    W = xp.squeeze(W, axis=-1)
    dfn, dfd = xp.asarray(dfn, dtype=W.dtype), xp.asarray(dfd, dtype=W.dtype)
    pval = _get_pvalue(W, _SimpleF(dfn, dfd), 'greater', xp=xp)
    return LeveneResult(W[()], pval[()])


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


@xp_capabilities(skip_backends=[('dask.array', 'no rankdata'),
                                ('cupy', 'no rankdata')], jax_jit=False)
@_axis_nan_policy_factory(FlignerResult, n_samples=None)
def fligner(*samples, center='median', proportiontocut=0.05, axis=0):
    r"""Perform Fligner-Killeen test for equality of variance.

    Fligner's test tests the null hypothesis that all input samples
    are from populations with equal variances.  Fligner-Killeen's test is
    distribution free when populations are identical [2]_.

    Parameters
    ----------
    sample1, sample2, ... : array_like
        Arrays of sample data.  Need not be the same length.
    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.
        If ``None``, the input will be raveled before computing the statistic.