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

Code before:

@xp_capabilities(skip_backends=[('cupy', 'needs rankdata'),
                                ('dask.array', 'needs rankdata')],
                 cpu_only=True, jax_jit=False)
@_axis_nan_policy_factory(CramerVonMisesResult, n_samples=2, too_small=1,
                          result_to_tuple=_cvm_result_to_tuple)
def cramervonmises_2samp(x, y, method='auto', *, axis=0):
    r"""Perform the two-sample Cramér-von Mises test for goodness of fit.

    This is the two-sample version of the Cramér-von Mises test ([1]_):
    for two independent samples :math:`X_1, ..., X_n` and
    :math:`Y_1, ..., Y_m`, the null hypothesis is that the samples
    come from the same (unspecified) continuous distribution.

    The statistic :math:`T` is defined as in [1]_:

    .. math::
        T = \frac{nm}{n+m}\omega^2 =
        \frac{U}{n m (n+m)} - \frac{4 m n - 1}{6(m+n)}

    where :math:`U` is defined as below. The function :math:`r()` here denotes
    the rank of the element within the pooled sample of size :math:`n + m`, with
    ties assigned mid-rank values:

    .. math::
        U = n \sum_{i=1}^n (r(X_i)-i)^2 + m \sum_{j=1}^m (r(Y_j)-j)^2

    Parameters
    ----------
    x : array_like
        A 1-D array of observed values of the random variables :math:`X_i`.
        Must contain at least two observations.
    y : array_like
        A 1-D array of observed values of the random variables :math:`Y_i`.
        Must contain at least two observations.
    method : {'auto', 'asymptotic', 'exact'}, optional
        The method used to compute the p-value, see Notes for details.
        The default is 'auto'.
    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.

    Returns
    -------
    res : object with attributes
        statistic : float
            Cramér-von Mises statistic :math:`T`.
        pvalue : float
            The p-value.

Review comment (suggestion):
I commented above that $x_i$ was undefined. That was assuming that $X_i$ is supposed to represent a random variable and $x_i$ is our observation of that random variable, an element in the sample. From that perspective, I'd think that $X_i$ and $Y_j$ here should be $x_i$ and $y_j$, which would also need to be defined.

Code after:

@xp_capabilities(skip_backends=[('cupy', 'needs rankdata'),
                                ('dask.array', 'needs rankdata')],
                 cpu_only=True, jax_jit=False)
@_axis_nan_policy_factory(CramerVonMisesResult, n_samples=2, too_small=1,
                          result_to_tuple=_cvm_result_to_tuple)
def cramervonmises_2samp(x, y, method='auto', *, axis=0):
    r"""Perform the two-sample Cramér-von Mises test for goodness of fit.

    This is the two-sample version of the Cramér-von Mises test ([1]_):
    for two independent samples :math:`X_1, ..., X_n` and
    :math:`Y_1, ..., Y_m`, the null hypothesis is that the samples
    come from the same (unspecified) continuous distribution.

    The test statistic :math:`T` is defined as in [1]_:

    .. math::
        T = \frac{nm}{n+m}\omega^2 =
        \frac{U}{n m (n+m)} - \frac{4 m n - 1}{6(m+n)}

    where :math:`U` is defined as below, and :math:`\omega^2` is the Cramér-von
    Mises criterion. The function :math:`r(\cdot)` here denotes the rank of the
    observed values :math:`x_i` and :math:`y_j` within the pooled sample of size
    :math:`n + m`, with ties assigned mid-rank values:

    .. math::
        U = n \sum_{i=1}^n (r(x_i)-i)^2 + m \sum_{j=1}^m (r(y_j)-j)^2

    Parameters
    ----------
    x : array_like
        A 1-D array of observed values of the random variables :math:`X_i`.
        Must contain at least two observations.
    y : array_like
        A 1-D array of observed values of the random variables :math:`Y_i`.
        Must contain at least two observations.
    method : {'auto', 'asymptotic', 'exact'}, optional
        The method used to compute the p-value, see Notes for details.
        The default is 'auto'.
    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.

    Returns
    -------
    res : object with attributes
        statistic : float
            Cramér-von Mises statistic :math:`T`.
        pvalue : float