Skip to content

Commit 7dd451d

Browse files
nathalierjreback
authored andcommitted
BUG: iloc misbehavior with pd.Series: sometimes returns pd.Categorical, fixes #14580
closes #14580 Author: Nathalie Rud <[email protected]> Closes #14642 from nathalier/nath-working and squashes the following commits: f6b1790 [Nathalie Rud] DOC: add whatsnew entry for bug GH #14580 fix bb9b601 [Nathalie Rud] TST: add test to cover bug GH #14580 9a69ca5 [Nathalie Rud] CLN: refactor _getitem_axis() of _iLocIndexer class 5b5ead4 [Nathalie Rud] BUG: fix iloc with pd.Series on pd.Categorical
1 parent caab85b commit 7dd451d

File tree

3 files changed

+54
-17
lines changed

3 files changed

+54
-17
lines changed

doc/source/whatsnew/v0.20.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ Bug Fixes
311311

312312

313313

314+
- Bug in ``Series.iloc`` where a ``Categorical`` object for list-like indexes input was returned, where a ``Series`` was expected. (:issue:`14580`)
314315

315316

316317

pandas/core/indexing.py

+32-17
Original file line numberDiff line numberDiff line change
@@ -1596,6 +1596,27 @@ def _get_slice_axis(self, slice_obj, axis=0):
15961596
else:
15971597
return self.obj.take(slice_obj, axis=axis, convert=False)
15981598

1599+
def _get_list_axis(self, key_list, axis=0):
1600+
"""
1601+
Return Series values by list or array of integers
1602+
1603+
Parameters
1604+
----------
1605+
key_list : list-like positional indexer
1606+
axis : int (can only be zero)
1607+
1608+
Returns
1609+
-------
1610+
Series object
1611+
"""
1612+
1613+
# validate list bounds
1614+
self._is_valid_list_like(key_list, axis)
1615+
1616+
# force an actual list
1617+
key_list = list(key_list)
1618+
return self.obj.take(key_list, axis=axis, convert=False)
1619+
15991620
def _getitem_axis(self, key, axis=0):
16001621

16011622
if isinstance(key, slice):
@@ -1606,26 +1627,20 @@ def _getitem_axis(self, key, axis=0):
16061627
self._has_valid_type(key, axis)
16071628
return self._getbool_axis(key, axis=axis)
16081629

1609-
# a single integer or a list of integers
1610-
else:
1611-
1612-
if is_list_like_indexer(key):
1613-
1614-
# validate list bounds
1615-
self._is_valid_list_like(key, axis)
1616-
1617-
# force an actual list
1618-
key = list(key)
1630+
# a list of integers
1631+
elif is_list_like_indexer(key):
1632+
return self._get_list_axis(key, axis=axis)
16191633

1620-
else:
1621-
key = self._convert_scalar_indexer(key, axis)
1634+
# a single integer
1635+
else:
1636+
key = self._convert_scalar_indexer(key, axis)
16221637

1623-
if not is_integer(key):
1624-
raise TypeError("Cannot index by location index with a "
1625-
"non-integer key")
1638+
if not is_integer(key):
1639+
raise TypeError("Cannot index by location index with a "
1640+
"non-integer key")
16261641

1627-
# validate the location
1628-
self._is_valid_integer(key, axis)
1642+
# validate the location
1643+
self._is_valid_integer(key, axis)
16291644

16301645
return self._get_loc(key, axis=axis)
16311646

pandas/tests/test_categorical.py

+21
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,27 @@ def test_getitem_listlike(self):
5454
expected = c[np.array([100000]).astype(np.int64)].codes
5555
self.assert_numpy_array_equal(result, expected)
5656

57+
def test_getitem_category_type(self):
58+
# GH 14580
59+
# test iloc() on Series with Categorical data
60+
61+
s = pd.Series([1, 2, 3]).astype('category')
62+
63+
# get slice
64+
result = s.iloc[0:2]
65+
expected = pd.Series([1, 2]).astype('category', categories=[1, 2, 3])
66+
tm.assert_series_equal(result, expected)
67+
68+
# get list of indexes
69+
result = s.iloc[[0, 1]]
70+
expected = pd.Series([1, 2]).astype('category', categories=[1, 2, 3])
71+
tm.assert_series_equal(result, expected)
72+
73+
# get boolean array
74+
result = s.iloc[[True, False, False]]
75+
expected = pd.Series([1]).astype('category', categories=[1, 2, 3])
76+
tm.assert_series_equal(result, expected)
77+
5778
def test_setitem(self):
5879

5980
# int/positional

0 commit comments

Comments
 (0)