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

Code before:
    .. [2] https://en.wikipedia.org/wiki/Kruskal-Wallis_one-way_analysis_of_variance

    Examples
    --------
    >>> from scipy import stats
    >>> x = [1, 3, 5, 7, 9]
    >>> y = [2, 4, 6, 8, 10]
    >>> stats.kruskal(x, y)
    KruskalResult(statistic=0.2727272727272734, pvalue=0.6015081344405895)

    >>> x = [1, 1, 1]
    >>> y = [2, 2, 2]
    >>> z = [2, 2]
    >>> stats.kruskal(x, y, z)
    KruskalResult(statistic=7.0, pvalue=0.0301973834223185)

    """
    num_groups = len(samples)
    if num_groups < 2:
        raise ValueError("Need at least two groups in stats.kruskal()")

    n = np.asarray([sample.shape[-1] for sample in samples])
    totaln = np.sum(n)

    if np.any(n) < 1:  # Only needed for `test_axis_nan_policy`
        raise ValueError("Inputs must not be empty.")

    alldata = np.concatenate(samples, axis=-1)
    ranked, t = _rankdata(alldata, method='average', return_ties=True)

    # ties = tiecorrect(ranked)
    ties = 1 - (t**3 - t).sum(axis=-1) / (totaln**3 - totaln)

    # Compute sum^2/n for each group and sum
    j = np.cumsum(n, axis=-1)
    ssbn = np.sum(ranked[..., :j[0]], axis=-1)**2 / n[0]
    for i in range(1, num_groups):
        ssbn += np.sum(ranked[..., j[i-1]:j[i]], axis=-1)**2 / n[i]

    h = 12.0 / (totaln * (totaln + 1)) * ssbn - 3 * (totaln + 1)
    df = num_groups - 1
    h /= ties

    chi2 = _SimpleChi2(df)
    pvalue = _get_pvalue(h, chi2, alternative='greater', symmetric=False, xp=np)
    return KruskalResult(h, pvalue)


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


Review comment (suggestion):
The `_axis_nan_policy` tests just need this to compare the behavior of the wrapped and unwrapped function. The user will never see this.
```
> stats.kruskal([], [1], axis=-1)
<ipython-input-8-f34d1b36fc2d>:1: SmallSampleWarning: One or more sample arguments is too small; all returned values will be NaN. See documentation for sample size requirements.
  stats.kruskal([], [1], axis=-1)
Out: KruskalResult(statistic=np.float64(nan), pvalue=np.float64(nan))
```

Code after:
       Association, Vol. 47, Issue 260, pp. 583-621, 1952.
    .. [2] https://en.wikipedia.org/wiki/Kruskal-Wallis_one-way_analysis_of_variance

    Examples
    --------
    >>> from scipy import stats
    >>> x = [1, 3, 5, 7, 9]
    >>> y = [2, 4, 6, 8, 10]
    >>> stats.kruskal(x, y)
    KruskalResult(statistic=0.2727272727272734, pvalue=0.6015081344405895)

    >>> x = [1, 1, 1]
    >>> y = [2, 2, 2]
    >>> z = [2, 2]
    >>> stats.kruskal(x, y, z)
    KruskalResult(statistic=7.0, pvalue=0.0301973834223185)

    """
    num_groups = len(samples)
    if num_groups < 2:
        raise ValueError("Need at least two groups in stats.kruskal()")

    n = [sample.shape[-1] for sample in samples]
    totaln = sum(n)
    if np.any(n) < 1:  # Only needed for `test_axis_nan_policy`
        raise ValueError("Inputs must not be empty.")

    alldata = np.concatenate(samples, axis=-1)
    ranked, t = _rankdata(alldata, method='average', return_ties=True)
    ties = 1 - (t**3 - t).sum(axis=-1) / (totaln**3 - totaln)  # tiecorrect(ranked)

    # Compute sum^2/n for each group and sum
    j = list(itertools.accumulate(n, initial=0))
    ssbn = sum(np.sum(ranked[..., j[i]:j[i + 1]], axis=-1)**2 / n[i]
               for i in range(num_groups))

    h = 12.0 / (totaln * (totaln + 1)) * ssbn - 3 * (totaln + 1)
    df = num_groups - 1
    h /= ties

    chi2 = _SimpleChi2(df)
    pvalue = _get_pvalue(h, chi2, alternative='greater', symmetric=False, xp=np)
    return KruskalResult(h, pvalue)


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


@xp_capabilities(np_only=True)
@_axis_nan_policy_factory(FriedmanchisquareResult, n_samples=None, paired=True)