Skip to content

Commit 43c4500

Browse files
TomAugspurgerPingviinituutti
authored andcommitted
BUG/PERF: Use EA in Index.get_value (pandas-dev#24204)
1 parent 0982067 commit 43c4500

File tree

3 files changed

+30
-1
lines changed

3 files changed

+30
-1
lines changed

doc/source/whatsnew/v0.24.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -1213,6 +1213,7 @@ Performance Improvements
12131213
- Improved performance of :func:`Series.describe` in case of numeric dtpyes (:issue:`21274`)
12141214
- Improved performance of :func:`pandas.core.groupby.GroupBy.rank` when dealing with tied rankings (:issue:`21237`)
12151215
- Improved performance of :func:`DataFrame.set_index` with columns consisting of :class:`Period` objects (:issue:`21582`, :issue:`21606`)
1216+
- Improved performance of :meth:`Series.at` and :meth:`Index.get_value` for Extension Arrays values (e.g. :class:`Categorical`) (:issue:`24204`)
12161217
- Improved performance of membership checks in :class:`Categorical` and :class:`CategoricalIndex`
12171218
(i.e. ``x in cat``-style checks are much faster). :meth:`CategoricalIndex.contains`
12181219
is likewise much faster (:issue:`21369`, :issue:`21508`)

pandas/core/indexes/base.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -4281,7 +4281,8 @@ def get_value(self, series, key):
42814281

42824282
# if we have something that is Index-like, then
42834283
# use this, e.g. DatetimeIndex
4284-
s = getattr(series, '_values', None)
4284+
# Things like `Series._get_value` (via .at) pass the EA directly here.
4285+
s = getattr(series, '_values', series)
42854286
if isinstance(s, (ExtensionArray, Index)) and is_scalar(key):
42864287
# GH 20882, 21257
42874288
# Unify Index and ExtensionArray treatment

pandas/tests/arrays/categorical/test_indexing.py

+27
Original file line numberDiff line numberDiff line change
@@ -239,3 +239,30 @@ def test_mask_with_boolean_raises(index):
239239

240240
with pytest.raises(ValueError, match='NA / NaN'):
241241
s[idx]
242+
243+
244+
@pytest.fixture
245+
def non_coercible_categorical(monkeypatch):
246+
"""
247+
Monkeypatch Categorical.__array__ to ensure no implicit conversion.
248+
249+
Raises
250+
------
251+
ValueError
252+
When Categorical.__array__ is called.
253+
"""
254+
# TODO(Categorical): identify other places where this may be
255+
# useful and move to a conftest.py
256+
def array(self, dtype=None):
257+
raise ValueError("I cannot be converted.")
258+
259+
with monkeypatch.context() as m:
260+
m.setattr(Categorical, "__array__", array)
261+
yield
262+
263+
264+
def test_series_at(non_coercible_categorical):
265+
arr = Categorical(['a', 'b', 'c'])
266+
ser = Series(arr)
267+
result = ser.at[0]
268+
assert result == 'a'

0 commit comments

Comments
 (0)