code: def quantile(a, q, weights=None, axis=None, keepdims: bool = False):
      """
      Compute the weighted quantiles along the specified axis
  
      After https://en.wikipedia.org/wiki/Percentile#Weighted_percentile
  
      If `q` is a single quantile and `axis=None`, then the result
      is a scalar. If multiple quantiles are given, first axis of
      the result corresponds to the quantiles. The other axes are
      the axes that remain after the reduction of `a`.
  
      :param a: Array containing numbers whose median is desired. If `a` is not an
          array, a conversion is attempted
      :param q: Quantile or sequence of quantiles to compute, which must be between 0 and 1 inclusive
      :param weights: Array containing weights for the elements of `a`. If `weights` is not an
          array, a conversion is attempted.
      :param axis: Axis or axes along which the quantiles are computed. The
          default is to compute the quantile(s) along a flattened. Type is int, tuple of int, None, optional.
          version of the array
      :param bool keepdims: If this is set to True, the axes which are reduced are left
          in the result as dimensions with size one.
      :return: scalar or ndarray
      """
      q = (
          q
          if not hasattr(q, "__iter__")
          else q[0]
          if len(q) == 1
          else tuple(q)
      )
      if weights is None:
          return np.quantile(a, q, axis=axis, keepdims=keepdims)
      elif axis is None:
          raveled_data = np.ravel(a)
          idx = np.argsort(raveled_data)
          sorted_data = raveled_data[idx]
          sorted_weights = np.ravel(weights)[idx]
          Sn = np.cumsum(sorted_weights)  # noqa: N806
          Pn = (Sn - 0.5 * sorted_weights) / Sn[-1]  # noqa: N806
          y = np.interp(q, Pn, sorted_data)
          if keepdims:
              y = y.reshape((*y.shape, *(1,) * np.ndim(a)))
  
          return y
      else:
          # Move the dimensions which are reduced to the back
          axis = [axis] if not hasattr(axis, "__iter__") else axis
          destination = list(range(-len(axis), 0, 1))
          a_moved = np.moveaxis(a, source=axis, destination=destination)
  
          # Reshape into a 2D-array, with the first axis the dimensions
          # that are not reduced, and the second the dimensions that are reduced
          shape = (-1, np.prod(a_moved.shape[-len(axis) :]))
          a_shaped = a_moved.reshape(shape)
  
          w = np.moveaxis(
              weights, source=axis, destination=destination
          ).reshape(shape)
  
          # Determine the quantiles and reshape backwards
          y = np.array(
              [quantile(x, q, u) for x, u in zip(a_shaped, w)]
          ).T
          if keepdims:
              shape = (
                  *y.shape[:-1],
                  *(
                      1 if i in axis else x
                      for i, x in enumerate(a.shape)
                  ),
              )
          else:
              shape = *y.shape[:-1], *a_moved.shape[: -len(destination)]
  
          y = y.reshape(shape)
          return y
  
file_path: popmon/popmon/stats/numpy.py
imports: import numpy
  import pandas
label_desc: Use image node_id 4 for calling a global function with example usage: quantile(a, q, weights, axis, keepdims) and returns: np, y, y