Skip to content

Commit c2ea877

Browse files
topper-123Pingviinituutti
authored andcommitted
API: Make Categorical.searchsorted returns a scalar when supplied a scalar (pandas-dev#23466)
1 parent ebfc96c commit c2ea877

File tree

3 files changed

+14
-14
lines changed

3 files changed

+14
-14
lines changed

doc/source/whatsnew/v0.24.0.rst

+2
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,8 @@ Other API Changes
10071007
- Slicing a single row of a DataFrame with multiple ExtensionArrays of the same type now preserves the dtype, rather than coercing to object (:issue:`22784`)
10081008
- :class:`DateOffset` attribute `_cacheable` and method `_should_cache` have been removed (:issue:`23118`)
10091009
- Comparing :class:`Timedelta` to be less or greater than unknown types now raises a ``TypeError`` instead of returning ``False`` (:issue:`20829`)
1010+
- :meth:`Categorical.searchsorted`, when supplied a scalar value to search for, now returns a scalar instead of an array (:issue:`23466`).
1011+
- :meth:`Categorical.searchsorted` now raises a ``KeyError`` rather that a ``ValueError``, if a searched for key is not found in its categories (:issue:`23466`).
10101012
- :meth:`Index.hasnans` and :meth:`Series.hasnans` now always return a python boolean. Previously, a python or a numpy boolean could be returned, depending on circumstances (:issue:`23294`).
10111013
- The order of the arguments of :func:`DataFrame.to_html` and :func:`DataFrame.to_string` is rearranged to be consistent with each other. (:issue:`23614`)
10121014

pandas/core/arrays/categorical.py

+5-7
Original file line numberDiff line numberDiff line change
@@ -1344,15 +1344,13 @@ def searchsorted(self, value, side='left', sorter=None):
13441344
"ordered one")
13451345

13461346
from pandas.core.series import Series
1347+
codes = _get_codes_for_values(Series(value).values, self.categories)
1348+
if -1 in codes:
1349+
raise KeyError("Value(s) to be inserted must be in categories.")
13471350

1348-
values_as_codes = _get_codes_for_values(Series(value).values,
1349-
self.categories)
1351+
codes = codes[0] if is_scalar(value) else codes
13501352

1351-
if -1 in values_as_codes:
1352-
raise ValueError("Value(s) to be inserted must be in categories.")
1353-
1354-
return self.codes.searchsorted(values_as_codes, side=side,
1355-
sorter=sorter)
1353+
return self.codes.searchsorted(codes, side=side, sorter=sorter)
13561354

13571355
def isna(self):
13581356
"""

pandas/tests/arrays/categorical/test_analytics.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,10 @@ def test_searchsorted(self):
8585

8686
# Searching for single item argument, side='left' (default)
8787
res_cat = c1.searchsorted('apple')
88+
assert res_cat == 2
89+
8890
res_ser = s1.searchsorted('apple')
89-
exp = np.array([2], dtype=np.intp)
90-
tm.assert_numpy_array_equal(res_cat, exp)
91-
tm.assert_numpy_array_equal(res_ser, exp)
91+
assert res_ser == 2
9292

9393
# Searching for single item array, side='left' (default)
9494
res_cat = c1.searchsorted(['bread'])
@@ -105,13 +105,13 @@ def test_searchsorted(self):
105105
tm.assert_numpy_array_equal(res_ser, exp)
106106

107107
# Searching for a single value that is not from the Categorical
108-
pytest.raises(ValueError, lambda: c1.searchsorted('cucumber'))
109-
pytest.raises(ValueError, lambda: s1.searchsorted('cucumber'))
108+
pytest.raises(KeyError, lambda: c1.searchsorted('cucumber'))
109+
pytest.raises(KeyError, lambda: s1.searchsorted('cucumber'))
110110

111111
# Searching for multiple values one of each is not from the Categorical
112-
pytest.raises(ValueError,
112+
pytest.raises(KeyError,
113113
lambda: c1.searchsorted(['bread', 'cucumber']))
114-
pytest.raises(ValueError,
114+
pytest.raises(KeyError,
115115
lambda: s1.searchsorted(['bread', 'cucumber']))
116116

117117
# searchsorted call for unordered Categorical

0 commit comments

Comments
 (0)