code: def wilcoxon(
      x,
      y=None,
      zero_method="wilcox",
      correction=False,
      alternative="two-sided",
      mode="auto",
  ):
      """Calculate the Wilcoxon signed-rank test.
  
      The Wilcoxon signed-rank test tests the null hypothesis that two
      related paired samples come from the same distribution. In particular,
      it tests whether the distribution of the differences x - y is symmetric
      about zero. It is a non-parametric version of the paired T-test.
  
      Parameters
      ----------
      x : array_like
          Either the first set of measurements (in which case ``y`` is the second
          set of measurements), or the differences between two sets of
          measurements (in which case ``y`` is not to be specified.)  Must be
          one-dimensional.
      y : array_like, optional
          Either the second set of measurements (if ``x`` is the first set of
          measurements), or not specified (if ``x`` is the differences between
          two sets of measurements.)  Must be one-dimensional.
      zero_method : {"pratt", "wilcox", "zsplit"}, optional
          The following options are available (default is "wilcox"):
  
            * "pratt": Includes zero-differences in the ranking process,
              but drops the ranks of the zeros, see [4]_, (more conservative).
            * "wilcox": Discards all zero-differences, the default.
            * "zsplit": Includes zero-differences in the ranking process and
              split the zero rank between positive and negative ones.
      correction : bool, optional
          If True, apply continuity correction by adjusting the Wilcoxon rank
          statistic by 0.5 towards the mean value when computing the
          z-statistic if a normal approximation is used.  Default is False.
      alternative : {"two-sided", "greater", "less"}, optional
          The alternative hypothesis to be tested, see Notes. Default is
          "two-sided".
      mode : {"auto", "exact", "approx"}
          Method to calculate the p-value, see Notes. Default is "auto".
  
      Returns
      -------
      statistic : float
          If ``alternative`` is "two-sided", the sum of the ranks of the
          differences above or below zero, whichever is smaller.
          Otherwise the sum of the ranks of the differences above zero.
      pvalue : float
          The p-value for the test depending on ``alternative`` and ``mode``.
  
      See Also
      --------
      kruskal, mannwhitneyu
  
      Notes
      -----
      The test has been introduced in [4]_. Given n independent samples
      (xi, yi) from a bivariate distribution (i.e. paired samples),
      it computes the differences di = xi - yi. One assumption of the test
      is that the differences are symmetric, see [2]_.
      The two-sided test has the null hypothesis that the median of the
      differences is zero against the alternative that it is different from
      zero. The one-sided test has the null hypothesis that the median is
      positive against the alternative that it is negative
      (``alternative == 'less'``), or vice versa (``alternative == 'greater.'``).
  
      To derive the p-value, the exact distribution (``mode == 'exact'``)
      can be used for sample sizes of up to 25. The default ``mode == 'auto'``
      uses the exact distribution if there are at most 25 observations and no
      ties, otherwise a normal approximation is used (``mode == 'approx'``).
  
      The treatment of ties can be controlled by the parameter `zero_method`.
      If ``zero_method == 'pratt'``, the normal approximation is adjusted as in
      [5]_. A typical rule is to require that n > 20 ([2]_, p. 383).
  
      References
      ----------
      .. [1] https://en.wikipedia.org/wiki/Wilcoxon_signed-rank_test
      .. [2] Conover, W.J., Practical Nonparametric Statistics, 1971.
      .. [3] Pratt, J.W., Remarks on Zeros and Ties in the Wilcoxon Signed
         Rank Procedures, Journal of the American Statistical Association,
         Vol. 54, 1959, pp. 655-667. :doi:`10.1080/01621459.1959.10501526`
      .. [4] Wilcoxon, F., Individual Comparisons by Ranking Methods,
         Biometrics Bulletin, Vol. 1, 1945, pp. 80-83. :doi:`10.2307/3001968`
      .. [5] Cureton, E.E., The Normal Approximation to the Signed-Rank
         Sampling Distribution When Zero Differences are Present,
         Journal of the American Statistical Association, Vol. 62, 1967,
         pp. 1068-1069. :doi:`10.1080/01621459.1967.10500917`
  
      Examples
      --------
      In [4]_, the differences in height between cross- and self-fertilized
      corn plants is given as follows:
  
      >>> d = [6, 8, 14, 16, 23, 24, 28, 29, 41, -48, 49, 56, 60, -67, 75]
  
      Cross-fertilized plants appear to be be higher. To test the null
      hypothesis that there is no height difference, we can apply the
      two-sided test:
  
      >>> from scipy.stats import wilcoxon
      >>> w, p = wilcoxon(d)
      >>> w, p
      (24.0, 0.041259765625)
  
      Hence, we would reject the null hypothesis at a confidence level of 5%,
      concluding that there is a difference in height between the groups.
      To confirm that the median of the differences can be assumed to be
      positive, we use:
  
      >>> w, p = wilcoxon(d, alternative='greater')
      >>> w, p
      (96.0, 0.0206298828125)
  
      This shows that the null hypothesis that the median is negative can be
      rejected at a confidence level of 5% in favor of the alternative that
      the median is greater than zero. The p-values above are exact. Using the
      normal approximation gives very similar values:
  
      >>> w, p = wilcoxon(d, mode='approx')
      >>> w, p
      (24.0, 0.04088813291185591)
  
      Note that the statistic changed to 96 in the one-sided case (the sum
      of ranks of positive differences) whereas it is 24 in the two-sided
      case (the minimum of sum of ranks above and below zero).
  
      """
      if mode not in ["auto", "approx", "exact"]:
          raise ValueError(
              "mode must be either 'auto', 'approx' or 'exact'"
          )
  
      if zero_method not in ["wilcox", "pratt", "zsplit"]:
          raise ValueError(
              "Zero method must be either 'wilcox' "
              "or 'pratt' or 'zsplit'"
          )
  
      if alternative not in ["two-sided", "less", "greater"]:
          raise ValueError(
              "Alternative must be either 'two-sided', "
              "'greater' or 'less'"
          )
  
      if y is None:
          d = asarray(x)
          if d.ndim > 1:
              raise ValueError("Sample x must be one-dimensional.")
      else:
          x, y = map(asarray, (x, y))
          if x.ndim > 1 or y.ndim > 1:
              raise ValueError(
                  "Samples x and y must be one-dimensional."
              )
          if len(x) != len(y):
              raise ValueError(
                  "The samples x and y must have the same length."
              )
          d = x - y
  
      if mode == "auto":
          if len(d) <= 25:
              mode = "exact"
          else:
              mode = "approx"
  
      n_zero = np.sum(d == 0)
      if n_zero > 0 and mode == "exact":
          mode = "approx"
          warnings.warn(
              "Exact p-value calculation does not work if there are "
              "ties. Switching to normal approximation."
          )
  
      if mode == "approx":
          if zero_method in ["wilcox", "pratt"]:
              if n_zero == len(d):
                  raise ValueError(
                      "zero_method 'wilcox' and 'pratt' do not "
                      "work if x - y is zero for all elements."
                  )
          if zero_method == "wilcox":
              # Keep all non-zero differences
              d = compress(np.not_equal(d, 0), d)
  
      count = len(d)
      if count < 10 and mode == "approx":
          warnings.warn(
              "Sample size too small for normal approximation."
          )
  
      r = stats.rankdata(abs(d))
      r_plus = np.sum((d > 0) * r)
      r_minus = np.sum((d < 0) * r)
  
      if zero_method == "zsplit":
          r_zero = np.sum((d == 0) * r)
          r_plus += r_zero / 2.0
          r_minus += r_zero / 2.0
  
      # return min for two-sided test, but r_plus for one-sided test
      # the literature is not consistent here
      # r_plus is more informative since r_plus + r_minus = count*(count+1)/2,
      # i.e. the sum of the ranks, so r_minus and the min can be inferred
      # (If alternative='pratt', r_plus + r_minus = count*(count+1)/2 - r_zero.)
      # [3] uses the r_plus for the one-sided test, keep min for two-sided test
      # to keep backwards compatibility
      if alternative == "two-sided":
          T = min(r_plus, r_minus)
      else:
          T = r_plus
  
      if mode == "approx":
          mn = count * (count + 1.0) * 0.25
          se = count * (count + 1.0) * (2.0 * count + 1.0)
  
          if zero_method == "pratt":
              r = r[d != 0]
              # normal approximation needs to be adjusted, see Cureton (1967)
              mn -= n_zero * (n_zero + 1.0) * 0.25
              se -= n_zero * (n_zero + 1.0) * (2.0 * n_zero + 1.0)
  
          replist, repnum = find_repeats(r)
          if repnum.size != 0:
              # Correction for repeated elements.
              se -= 0.5 * (repnum * (repnum * repnum - 1)).sum()
  
          se = sqrt(se / 24)
  
          # apply continuity correction if applicable
          d = 0
          if correction:
              if alternative == "two-sided":
                  d = 0.5 * np.sign(T - mn)
              elif alternative == "less":
                  d = -0.5
              else:
                  d = 0.5
  
          # compute statistic and p-value using normal approximation
          z = (T - mn - d) / se
          if alternative == "two-sided":
              prob = 2.0 * distributions.norm.sf(abs(z))
          elif alternative == "greater":
              # large T = r_plus indicates x is greater than y; i.e.
              # accept alternative in that case and return small p-value (sf)
              prob = distributions.norm.sf(z)
          else:
              prob = distributions.norm.cdf(z)
      elif mode == "exact":
          # get frequencies cnt of the possible positive ranksums r_plus
          cnt = _get_wilcoxon_distr(count)
          # note: r_plus is int (ties not allowed), need int for slices below
          r_plus = int(r_plus)
          if alternative == "two-sided":
              if r_plus == (len(cnt) - 1) // 2:
                  # r_plus is the center of the distribution.
                  prob = 1.0
              else:
                  p_less = np.sum(cnt[: r_plus + 1]) / 2**count
                  p_greater = np.sum(cnt[r_plus:]) / 2**count
                  prob = 2 * min(p_greater, p_less)
          elif alternative == "greater":
              prob = np.sum(cnt[r_plus:]) / 2**count
          else:
              prob = np.sum(cnt[: r_plus + 1]) / 2**count
  
      return WilcoxonResult(T, prob)
  
imports: from __future__ import annotations
  import math
  import warnings
  from collections import namedtuple
  import numpy
  from numpy import isscalar, r_, log, around, unique, asarray, zeros, arange, sort, amin, amax, atleast_1d, sqrt, array, compress, pi, exp, ravel, count_nonzero, sin, cos, arctan2, hypot
  from scipy import optimize
  from scipy import special
  from .None import statlib
  from .None import stats
  from .stats import find_repeats, _contains_nan, _normtest_finish
  from .contingency import chi2_contingency
  from .None import distributions
  from ._distn_infrastructure import rv_generic
  from ._hypotests import _get_wilcoxon_distr
label_desc: Use image node_id 34 for calling a global function with example usage: wilcoxon(x, y, zero_method, correction, alternative, mode) and returns: WilcoxonResult