|
| 1 | +from __future__ import annotations |
| 2 | + |
| 3 | +from typing import TYPE_CHECKING |
| 4 | + |
1 | 5 | import numpy as np
|
2 | 6 |
|
3 | 7 | from pandas._libs import lib
|
| 8 | +from pandas._typing import ArrayLike |
4 | 9 |
|
5 |
| -from pandas.core.dtypes.common import is_list_like |
| 10 | +from pandas.core.dtypes.common import ( |
| 11 | + is_list_like, |
| 12 | + is_sparse, |
| 13 | +) |
| 14 | +from pandas.core.dtypes.missing import ( |
| 15 | + isna, |
| 16 | + na_value_for_dtype, |
| 17 | +) |
6 | 18 |
|
7 | 19 | from pandas.core.nanops import nanpercentile
|
8 | 20 |
|
| 21 | +if TYPE_CHECKING: |
| 22 | + from pandas.core.arrays import ExtensionArray |
| 23 | + |
| 24 | + |
| 25 | +def quantile_compat(values: ArrayLike, qs, interpolation: str, axis: int) -> ArrayLike: |
| 26 | + """ |
| 27 | + Compute the quantiles of the given values for each quantile in `qs`. |
| 28 | +
|
| 29 | + Parameters |
| 30 | + ---------- |
| 31 | + values : np.ndarray or ExtensionArray |
| 32 | + qs : a scalar or list of the quantiles to be computed |
| 33 | + interpolation : str |
| 34 | + axis : int |
| 35 | +
|
| 36 | + Returns |
| 37 | + ------- |
| 38 | + np.ndarray or ExtensionArray |
| 39 | + """ |
| 40 | + if isinstance(values, np.ndarray): |
| 41 | + fill_value = na_value_for_dtype(values.dtype, compat=False) |
| 42 | + mask = isna(values) |
| 43 | + result = quantile_with_mask(values, mask, fill_value, qs, interpolation, axis) |
| 44 | + else: |
| 45 | + result = quantile_ea_compat(values, qs, interpolation, axis) |
| 46 | + return result |
| 47 | + |
9 | 48 |
|
10 | 49 | def quantile_with_mask(
|
11 | 50 | values: np.ndarray,
|
@@ -75,3 +114,50 @@ def quantile_with_mask(
|
75 | 114 | result = lib.item_from_zerodim(result)
|
76 | 115 |
|
77 | 116 | return result
|
| 117 | + |
| 118 | + |
| 119 | +def quantile_ea_compat( |
| 120 | + values: ExtensionArray, qs, interpolation: str, axis: int |
| 121 | +) -> ExtensionArray: |
| 122 | + """ |
| 123 | + ExtensionArray compatibility layer for quantile_with_mask. |
| 124 | +
|
| 125 | + We pretend that an ExtensionArray with shape (N,) is actually (1, N,) |
| 126 | + for compatibility with non-EA code. |
| 127 | +
|
| 128 | + Parameters |
| 129 | + ---------- |
| 130 | + values : ExtensionArray |
| 131 | + qs : a scalar or list of the quantiles to be computed |
| 132 | + interpolation: str |
| 133 | + axis : int |
| 134 | +
|
| 135 | + Returns |
| 136 | + ------- |
| 137 | + ExtensionArray |
| 138 | + """ |
| 139 | + # TODO(EA2D): make-believe not needed with 2D EAs |
| 140 | + orig = values |
| 141 | + |
| 142 | + # asarray needed for Sparse, see GH#24600 |
| 143 | + mask = np.asarray(values.isna()) |
| 144 | + mask = np.atleast_2d(mask) |
| 145 | + |
| 146 | + values, fill_value = values._values_for_factorize() |
| 147 | + values = np.atleast_2d(values) |
| 148 | + |
| 149 | + result = quantile_with_mask(values, mask, fill_value, qs, interpolation, axis) |
| 150 | + |
| 151 | + if not is_sparse(orig.dtype): |
| 152 | + # shape[0] should be 1 as long as EAs are 1D |
| 153 | + |
| 154 | + if result.ndim == 1: |
| 155 | + # i.e. qs was originally a scalar |
| 156 | + assert result.shape == (1,), result.shape |
| 157 | + result = type(orig)._from_factorized(result, orig) |
| 158 | + |
| 159 | + else: |
| 160 | + assert result.shape == (1, len(qs)), result.shape |
| 161 | + result = type(orig)._from_factorized(result[0], orig) |
| 162 | + |
| 163 | + return result |
0 commit comments