Skip to main content
`Ctrl`+`K`
scipy.stats.

# quantile

scipy.stats.quantile(x, p, *, method='linear', axis=0, nan_policy='propagate', keepdims=None, weights=None)

  Compute the p-th quantile of the data along the specified axis.

  Parameters:
    x array_like of real numbers

      Data array.

    p array_like of float

      Probability or sequence of probabilities of the quantiles to compute. Values must be between 0 and 1 (inclusive). While `numpy.quantile` can only compute quantiles according to the Cartesian product of the first two arguments, this function enables calculation of quantiles at different probabilities for each axis slice by following broadcasting rules like those of `scipy.stats` reducing functions. See axis, keepdims, and the examples.

    method str, default: ‘linear’

      The method to use for estimating the quantile. The available options, numbered as they appear in [1], are:

      1. ‘inverted_cdf’

      2. ‘averaged_inverted_cdf’

      3. ‘closest_observation’

      4. ‘interpolated_inverted_cdf’

      5. ‘hazen’

      6. ‘weibull’

      7. ‘linear’ (default)

      8. ‘median_unbiased’

      9. ‘normal_unbiased’

      ‘harrell-davis’ is also available to compute the quantile estimate according to [2].

      ‘round_outward’, ‘round_inward’, and ‘round_nearest’ are available for use in trimming and winsorizing data.

      See Notes for details.

    axis int or None, default: 0

      Axis along which the quantiles are computed. `None` ravels both x and p before performing the calculation, without checking whether the original shapes were compatible. As in other `scipy.stats` functions, a positive integer axis is resolved after prepending 1s to the shape of x or p as needed until the two arrays have the same dimensionality. When providing x and p with different dimensionality, consider using negative axis integers for clarity.

    nan_policy str, default: ‘propagate’

      Defines how to handle NaNs in the input data x.

      - `propagate`: if a NaN is present in the axis slice (e.g. row) along which the statistic is computed, the corresponding slice of the output will contain NaN(s).

      - `omit`: NaNs will be omitted when performing the calculation. If insufficient data remains in the axis slice along which the statistic is computed, the corresponding slice of the output will contain NaN(s).

      - `raise`: if a NaN is present, a `ValueError` will be raised.

      If NaNs are present in p, a `ValueError` will be raised.

    keepdims bool, optional

      Consider the case in which x is 1-D and p is a scalar: the quantile is a reducing statistic, and the default behavior is to return a scalar. If keepdims is set to True, the axis will not be reduced away, and the result will be a 1-D array with one element.

      The general case is more subtle, since multiple quantiles may be requested for each axis-slice of x. For instance, if both x and p are 1-D and `p.size > 1`, no axis can be reduced away; there must be an axis to contain the number of quantiles given by `p.size`. Therefore:

      - By default, the axis will be reduced away if possible (i.e. if there is exactly one element of p per axis-slice of x).

      - If keepdims is set to True, the axis will not be reduced away.

      - If keepdims is set to False, the axis will be reduced away if possible, and an error will be raised otherwise.

    weights array_like of finite, non-negative real numbers

      Frequency weights; e.g., for counting number weights, `quantile(x, p, weights=weights)` is equivalent to `quantile(np.repeat(x, weights), p)`. Values other than finite counting numbers are accepted, but may not have valid statistical interpretations. Not compatible with `method='harrell-davis'` or those that begin with `'round_'`.

  Returns:
    quantile scalar or ndarray

      The resulting quantile(s). The dtype is the result dtype of x and p.

  See also

  `numpy.quantile`
  Trimming and winsorization transition guide

  Notes

  Given a sample x from an underlying distribution, `quantile` provides a nonparametric estimate of the inverse cumulative distribution function.

  By default, this is done by interpolating between adjacent elements in `y`, a sorted copy of x:

      (1-g)*y[j] + g*y[j+1]

  where the index `j` and coefficient `g` are the integral and fractional components of `p * (n-1)`, and `n` is the number of elements in the sample.

  This is a special case of Equation 1 of H&F [1]. More generally,

  - `j = (p*n + m - 1) // 1`, and

  - `g = (p*n + m - 1) % 1`,

  where `m` may be defined according to several different conventions. The preferred convention may be selected using the `method` parameter:

  `method` | number in H&F | `m`
  --- | --- | ---
  `interpolated_inverted_cdf` | 4 | `0`
  `hazen` | 5 | `1/2`
  `weibull` | 6 | `p`
  `linear` (default) | 7 | `1 - p`
  `median_unbiased` | 8 | `p/3 + 1/3`
  `normal_unbiased` | 9 | `p/4 + 3/8`

  Note that indices `j` and `j + 1` are clipped to the range `0` to `n - 1` when the results of the formula would be outside the allowed range of non-negative indices. When `j` is clipped to zero, `g` is set to zero as well. The `-1` in the formulas for `j` and `g` accounts for Python’s 0-based indexing.

  The table above includes only the estimators from [1] that are continuous functions of probability p (estimators 4-9). SciPy also provides the three discontinuous estimators from [1] (estimators 1-3), where `j` is defined as above, `m` is defined as follows, and `g` is `0` when `index = p*n + m - 1` is less than `0` and otherwise is defined below.

  1. `inverted_cdf`: `m = 0` and `g = int(index - j > 0)`

  2. `averaged_inverted_cdf`: `m = 0` and `g = (1 + int(index - j > 0)) / 2`

  3. `closest_observation`: `m = -1/2` and `g = 1 - int((index == j) & (j%2 == 1))`

  Note that for methods `inverted_cdf` and `averaged_inverted_cdf`, only the relative proportions of tied observations (and relative weights) affect the results; for all other methods, the total number of observations (and absolute weights) matter.

  A different strategy for computing quantiles from [2], `method='harrell-davis'`, uses a weighted combination of all elements. The weights are computed as:

  \[w_{n, i} = I_{i/n}(a, b) - I_{(i - 1)/n}(a, b)\]

  where \(n\) is the number of elements in the sample, \(i\) are the indices \(1, 2, ..., n-1, n\) of the sorted elements, \(a = p (n + 1)\), \(b = (1 - p)(n + 1)\), \(p\) is the probability of the quantile, and \(I\) is the regularized, lower incomplete beta function (`scipy.special.betainc`).

  `method='round_nearest'` is equivalent to indexing `y[j]`, where:

      j = int(np.round(p*n) if p < 0.5 else np.round(n*p - 1))

  This is useful when winsorizing data: replacing `p*n` of the most extreme observations with the next most extreme observation. `method='round_outward'` adjusts the direction of rounding to winsorize fewer elements:

      j = int(np.floor(p*n) if p < 0.5 else np.ceil(n*p - 1))

  and `method='round_inward'` rounds to winsorize more elements:

      j = int(np.ceil(p*n) if p < 0.5 else np.floor(n*p - 1))

  These methods are also useful for trimming data: removing `p*n` of the most extreme observations. See Trimming and winsorization transition guide for example applications.

  Array API Standard Support

  `quantile` has experimental support for Python Array API Standard compatible backends in addition to NumPy. Please consider testing these features by setting an environment variable `SCIPY_ARRAY_API=1` and providing CuPy, PyTorch, JAX, or Dask arrays as array arguments. The following combinations of backend and device (or other capability) are supported.

  Library | CPU | GPU
  --- | --- | ---
  NumPy | ✅ | n/a
  CuPy | n/a | ✅
  PyTorch | ✅ | ✅
  JAX | ⚠️ no JIT | ⚠️ no JIT
  Dask | ⛔ | n/a

  > See Support for the array API standard for more information.

  References

  [1] (1,2,3,4)

  R. J. Hyndman and Y. Fan, “Sample quantiles in statistical packages,” The American Statistician, 50(4), pp. 361-365, 1996

  [2] (1,2)

  Harrell, Frank E., and C. E. Davis. “A new distribution-free quantile estimator.” Biometrika 69.3 (1982): 635-640.

  Examples

      >>> import numpy as np
      >>> from scipy import stats
      >>> x = np.asarray([[10, 8, 7, 5, 4],
      ...                 [0, 1, 2, 3, 5]])

  Take the median of each row.

      >>> stats.quantile(x, 0.5, axis=-1)
      array([7.,  2.])

  Take a different quantile for each row.

      >>> stats.quantile(x, [[0.25], [0.75]], axis=-1, keepdims=True)
      array([[5.],
             [3.]])

  Take multiple quantiles for each row.

      >>> stats.quantile(x, [0.25, 0.75], axis=-1)
      array([[5., 8.],
             [1., 3.]])

  Take different quantiles for each row.

      >>> p = np.asarray([[0.25, 0.75],
      ...                 [0.5, 1.0]])
      >>> stats.quantile(x, p, axis=-1)
      array([[5., 8.],
             [2., 5.]])

  Take different quantiles for each column.

      >>> stats.quantile(x.T, p.T, axis=0)
      array([[5., 2.],
             [8., 5.]])