Skip to content

Commit 1d6ce0f

Browse files
jbrockmendelJulianWgs
authored andcommitted
CLN: remove unreachable quantile code (pandas-dev#40547)
1 parent 90fa80f commit 1d6ce0f

File tree

4 files changed

+40
-78
lines changed

4 files changed

+40
-78
lines changed

pandas/core/array_algos/quantile.py

+20-43
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,9 @@
44

55
import numpy as np
66

7-
from pandas._libs import lib
87
from pandas._typing import ArrayLike
98

10-
from pandas.core.dtypes.common import (
11-
is_list_like,
12-
is_sparse,
13-
)
9+
from pandas.core.dtypes.common import is_sparse
1410
from pandas.core.dtypes.missing import (
1511
isna,
1612
na_value_for_dtype,
@@ -22,16 +18,15 @@
2218
from pandas.core.arrays import ExtensionArray
2319

2420

25-
def quantile_compat(values: ArrayLike, qs, interpolation: str, axis: int) -> ArrayLike:
21+
def quantile_compat(values: ArrayLike, qs: np.ndarray, interpolation: str) -> ArrayLike:
2622
"""
2723
Compute the quantiles of the given values for each quantile in `qs`.
2824
2925
Parameters
3026
----------
3127
values : np.ndarray or ExtensionArray
32-
qs : a scalar or list of the quantiles to be computed
28+
qs : np.ndarray[float64]
3329
interpolation : str
34-
axis : int
3530
3631
Returns
3732
-------
@@ -40,18 +35,17 @@ def quantile_compat(values: ArrayLike, qs, interpolation: str, axis: int) -> Arr
4035
if isinstance(values, np.ndarray):
4136
fill_value = na_value_for_dtype(values.dtype, compat=False)
4237
mask = isna(values)
43-
return quantile_with_mask(values, mask, fill_value, qs, interpolation, axis)
38+
return _quantile_with_mask(values, mask, fill_value, qs, interpolation)
4439
else:
45-
return quantile_ea_compat(values, qs, interpolation, axis)
40+
return _quantile_ea_compat(values, qs, interpolation)
4641

4742

48-
def quantile_with_mask(
43+
def _quantile_with_mask(
4944
values: np.ndarray,
5045
mask: np.ndarray,
5146
fill_value,
52-
qs,
47+
qs: np.ndarray,
5348
interpolation: str,
54-
axis: int,
5549
) -> np.ndarray:
5650
"""
5751
Compute the quantiles of the given values for each quantile in `qs`.
@@ -66,11 +60,9 @@ def quantile_with_mask(
6660
fill_value : Scalar
6761
The value to interpret fill NA entries with
6862
For ExtensionArray, this is _values_for_factorize()[1]
69-
qs : a scalar or list of the quantiles to be computed
63+
qs : np.ndarray[float64]
7064
interpolation : str
7165
Type of interpolation
72-
axis : int
73-
Axis along which to compute quantiles.
7466
7567
Returns
7668
-------
@@ -80,12 +72,12 @@ def quantile_with_mask(
8072
-----
8173
Assumes values is already 2D. For ExtensionArray this means np.atleast_2d
8274
has been called on _values_for_factorize()[0]
75+
76+
Quantile is computed along axis=1.
8377
"""
84-
is_empty = values.shape[axis] == 0
85-
orig_scalar = not is_list_like(qs)
86-
if orig_scalar:
87-
# make list-like, unpack later
88-
qs = [qs]
78+
assert values.ndim == 2
79+
80+
is_empty = values.shape[1] == 0
8981

9082
if is_empty:
9183
# create the array of na_values
@@ -97,39 +89,31 @@ def quantile_with_mask(
9789
result = nanpercentile(
9890
values,
9991
np.array(qs) * 100,
100-
axis=axis,
10192
na_value=fill_value,
10293
mask=mask,
103-
ndim=values.ndim,
10494
interpolation=interpolation,
10595
)
10696

10797
result = np.array(result, copy=False)
10898
result = result.T
10999

110-
if orig_scalar:
111-
assert result.shape[-1] == 1, result.shape
112-
result = result[..., 0]
113-
result = lib.item_from_zerodim(result)
114-
115100
return result
116101

117102

118-
def quantile_ea_compat(
119-
values: ExtensionArray, qs, interpolation: str, axis: int
103+
def _quantile_ea_compat(
104+
values: ExtensionArray, qs: np.ndarray, interpolation: str
120105
) -> ExtensionArray:
121106
"""
122-
ExtensionArray compatibility layer for quantile_with_mask.
107+
ExtensionArray compatibility layer for _quantile_with_mask.
123108
124109
We pretend that an ExtensionArray with shape (N,) is actually (1, N,)
125110
for compatibility with non-EA code.
126111
127112
Parameters
128113
----------
129114
values : ExtensionArray
130-
qs : a scalar or list of the quantiles to be computed
115+
qs : np.ndarray[float64]
131116
interpolation: str
132-
axis : int
133117
134118
Returns
135119
-------
@@ -145,19 +129,12 @@ def quantile_ea_compat(
145129
arr, fill_value = values._values_for_factorize()
146130
arr = np.atleast_2d(arr)
147131

148-
result = quantile_with_mask(arr, mask, fill_value, qs, interpolation, axis)
132+
result = _quantile_with_mask(arr, mask, fill_value, qs, interpolation)
149133

150134
if not is_sparse(orig.dtype):
151135
# shape[0] should be 1 as long as EAs are 1D
152-
153-
if result.ndim == 1:
154-
# i.e. qs was originally a scalar
155-
assert result.shape == (1,), result.shape
156-
result = type(orig)._from_factorized(result, orig)
157-
158-
else:
159-
assert result.shape == (1, len(qs)), result.shape
160-
result = type(orig)._from_factorized(result[0], orig)
136+
assert result.shape == (1, len(qs)), result.shape
137+
result = type(orig)._from_factorized(result[0], orig)
161138

162139
# error: Incompatible return value type (got "ndarray", expected "ExtensionArray")
163140
return result # type: ignore[return-value]

pandas/core/internals/array_manager.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,9 @@ def quantile(
512512

513513
arrs = [ensure_block_shape(x, 2) for x in self.arrays]
514514
assert axis == 1
515-
new_arrs = [quantile_compat(x, qs, interpolation, axis=axis) for x in arrs]
515+
new_arrs = [
516+
quantile_compat(x, np.asarray(qs._values), interpolation) for x in arrs
517+
]
516518
for i, arr in enumerate(new_arrs):
517519
if arr.ndim == 2:
518520
assert arr.shape[0] == 1, arr.shape

pandas/core/internals/blocks.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1436,7 +1436,7 @@ def quantile(
14361436
assert axis == 1 # only ever called this way
14371437
assert is_list_like(qs) # caller is responsible for this
14381438

1439-
result = quantile_compat(self.values, qs, interpolation, axis)
1439+
result = quantile_compat(self.values, np.asarray(qs._values), interpolation)
14401440

14411441
return new_block(result, placement=self._mgr_locs, ndim=2)
14421442

pandas/core/nanops.py

+16-33
Original file line numberDiff line numberDiff line change
@@ -1644,7 +1644,7 @@ def f(x, y):
16441644

16451645

16461646
def _nanpercentile_1d(
1647-
values: np.ndarray, mask: np.ndarray, q, na_value: Scalar, interpolation
1647+
values: np.ndarray, mask: np.ndarray, q: np.ndarray, na_value: Scalar, interpolation
16481648
) -> Union[Scalar, np.ndarray]:
16491649
"""
16501650
Wrapper for np.percentile that skips missing values, specialized to
@@ -1655,7 +1655,7 @@ def _nanpercentile_1d(
16551655
values : array over which to find quantiles
16561656
mask : ndarray[bool]
16571657
locations in values that should be considered missing
1658-
q : scalar or array of quantile indices to find
1658+
q : np.ndarray[float64] of quantile indices to find
16591659
na_value : scalar
16601660
value to return for empty or all-null values
16611661
interpolation : str
@@ -1668,52 +1668,44 @@ def _nanpercentile_1d(
16681668
values = values[~mask]
16691669

16701670
if len(values) == 0:
1671-
if lib.is_scalar(q):
1672-
return na_value
1673-
else:
1674-
return np.array([na_value] * len(q), dtype=values.dtype)
1671+
return np.array([na_value] * len(q), dtype=values.dtype)
16751672

16761673
return np.percentile(values, q, interpolation=interpolation)
16771674

16781675

16791676
def nanpercentile(
16801677
values: np.ndarray,
1681-
q,
1678+
q: np.ndarray,
16821679
*,
1683-
axis: int,
16841680
na_value,
16851681
mask: np.ndarray,
1686-
ndim: int,
16871682
interpolation,
16881683
):
16891684
"""
16901685
Wrapper for np.percentile that skips missing values.
16911686
16921687
Parameters
16931688
----------
1694-
values : array over which to find quantiles
1695-
q : scalar or array of quantile indices to find
1696-
axis : {0, 1}
1689+
values : np.ndarray[ndim=2] over which to find quantiles
1690+
q : np.ndarray[float64] of quantile indices to find
16971691
na_value : scalar
16981692
value to return for empty or all-null values
16991693
mask : ndarray[bool]
17001694
locations in values that should be considered missing
1701-
ndim : {1, 2}
17021695
interpolation : str
17031696
17041697
Returns
17051698
-------
17061699
quantiles : scalar or array
17071700
"""
1701+
17081702
if values.dtype.kind in ["m", "M"]:
17091703
# need to cast to integer to avoid rounding errors in numpy
17101704
result = nanpercentile(
17111705
values.view("i8"),
17121706
q=q,
1713-
axis=axis,
17141707
na_value=na_value.view("i8"),
17151708
mask=mask,
1716-
ndim=ndim,
17171709
interpolation=interpolation,
17181710
)
17191711

@@ -1722,25 +1714,16 @@ def nanpercentile(
17221714
return result.astype(values.dtype)
17231715

17241716
if not lib.is_scalar(mask) and mask.any():
1725-
if ndim == 1:
1726-
return _nanpercentile_1d(
1727-
values, mask, q, na_value, interpolation=interpolation
1728-
)
1729-
else:
1730-
# for nonconsolidatable blocks mask is 1D, but values 2D
1731-
if mask.ndim < values.ndim:
1732-
mask = mask.reshape(values.shape)
1733-
if axis == 0:
1734-
values = values.T
1735-
mask = mask.T
1736-
result = [
1737-
_nanpercentile_1d(val, m, q, na_value, interpolation=interpolation)
1738-
for (val, m) in zip(list(values), list(mask))
1739-
]
1740-
result = np.array(result, dtype=values.dtype, copy=False).T
1741-
return result
1717+
# Caller is responsible for ensuring mask shape match
1718+
assert mask.shape == values.shape
1719+
result = [
1720+
_nanpercentile_1d(val, m, q, na_value, interpolation=interpolation)
1721+
for (val, m) in zip(list(values), list(mask))
1722+
]
1723+
result = np.array(result, dtype=values.dtype, copy=False).T
1724+
return result
17421725
else:
1743-
return np.percentile(values, q, axis=axis, interpolation=interpolation)
1726+
return np.percentile(values, q, axis=1, interpolation=interpolation)
17441727

17451728

17461729
def na_accum_func(values: ArrayLike, accum_func, *, skipna: bool) -> ArrayLike:

0 commit comments

Comments
 (0)