Skip to content

Commit 2749b62

Browse files
committed
BUG: CategoricalIndex.get_loc returns array even if it is unique
1 parent 80ef4e0 commit 2749b62

File tree

4 files changed

+92
-5
lines changed

4 files changed

+92
-5
lines changed

doc/source/whatsnew/v0.18.1.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,6 @@ Bug Fixes
8989
~~~~~~~~~
9090

9191
- Bug in ``value_counts`` when ``normalize=True`` and ``dropna=True`` where nulls still contributed to the normalized count (:issue:`12558`)
92+
93+
- Bug in ``CategoricalIndex.get_loc`` returns different result from
94+
normal ``Index`` (:issue:`12531`)

pandas/indexes/category.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -287,11 +287,7 @@ def get_loc(self, key, method=None):
287287
codes = self.categories.get_loc(key)
288288
if (codes == -1):
289289
raise KeyError(key)
290-
indexer, _ = self._engine.get_indexer_non_unique(np.array([codes]))
291-
if (indexer == -1).any():
292-
raise KeyError(key)
293-
294-
return indexer
290+
return self._engine.get_loc(codes)
295291

296292
def _can_reindex(self, indexer):
297293
""" always allow reindexing """

pandas/tests/indexes/test_category.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,50 @@ def test_get_indexer(self):
363363
self.assertRaises(NotImplementedError,
364364
lambda: idx2.get_indexer(idx1, method='nearest'))
365365

366+
def test_get_loc(self):
367+
# GH 12531
368+
cidx1 = CategoricalIndex(list('abcde'), categories=list('edabc'))
369+
idx1 = Index(list('abcde'))
370+
self.assertEqual(cidx1.get_loc('a'), idx1.get_loc('a'))
371+
self.assertEqual(cidx1.get_loc('e'), idx1.get_loc('e'))
372+
373+
for i in [cidx1, idx1]:
374+
with tm.assertRaises(KeyError):
375+
i.get_loc('NOT-EXIST')
376+
377+
# non-unique
378+
cidx2 = CategoricalIndex(list('aacded'), categories=list('edabc'))
379+
idx2 = Index(list('aacded'))
380+
# results in bool array
381+
res = cidx2.get_loc('d')
382+
self.assert_numpy_array_equal(res, idx2.get_loc('d'))
383+
self.assert_numpy_array_equal(res, np.array([False, False, False,
384+
True, False, True]))
385+
# unique element results in scalar
386+
res = cidx2.get_loc('e')
387+
self.assertEqual(res, idx2.get_loc('e'))
388+
self.assertEqual(res, 4)
389+
390+
for i in [cidx2, idx2]:
391+
with tm.assertRaises(KeyError):
392+
i.get_loc('NOT-EXIST')
393+
394+
# non-unique, slicable
395+
cidx3 = CategoricalIndex(list('aabbb'), categories=list('abc'))
396+
idx3 = Index(list('aabbb'))
397+
# results in slice
398+
res = cidx3.get_loc('a')
399+
self.assertEqual(res, idx3.get_loc('a'))
400+
self.assertEqual(res, slice(0, 2, None))
401+
402+
res = cidx3.get_loc('b')
403+
self.assertEqual(res, idx3.get_loc('b'))
404+
self.assertEqual(res, slice(2, 5, None))
405+
406+
for i in [cidx3, idx3]:
407+
with tm.assertRaises(KeyError):
408+
i.get_loc('c')
409+
366410
def test_repr_roundtrip(self):
367411

368412
ci = CategoricalIndex(['a', 'b'], categories=['a', 'b'], ordered=True)

pandas/tests/indexing/test_categorical.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,50 @@ def test_loc_listlike_dtypes(self):
180180
'that are in the categories'):
181181
df.loc[['a', 'x']]
182182

183+
def test_ix_categorical_index(self):
184+
df = pd.DataFrame(np.random.randn(3, 3),
185+
index=list('ABC'), columns=list('XYZ'))
186+
cdf = df.copy()
187+
cdf.index = pd.CategoricalIndex(df.index)
188+
cdf.columns = pd.CategoricalIndex(df.columns)
189+
190+
expect = pd.Series(df.ix['A', :], index=cdf.columns, name='A')
191+
assert_series_equal(cdf.ix['A', :], expect)
192+
193+
expect = pd.Series(df.ix[:, 'X'], index=cdf.index, name='X')
194+
assert_series_equal(cdf.ix[:, 'X'], expect)
195+
196+
expect = pd.DataFrame(df.ix[['A', 'B'], :], columns=cdf.columns,
197+
index=pd.CategoricalIndex(list('AB')))
198+
assert_frame_equal(cdf.ix[['A', 'B'], :], expect)
199+
200+
expect = pd.DataFrame(df.ix[:, ['X', 'Y']], index=cdf.index,
201+
columns=pd.CategoricalIndex(list('XY')))
202+
assert_frame_equal(cdf.ix[:, ['X', 'Y']], expect)
203+
204+
# non-unique
205+
df = pd.DataFrame(np.random.randn(3, 3),
206+
index=list('ABA'), columns=list('XYX'))
207+
cdf = df.copy()
208+
cdf.index = pd.CategoricalIndex(df.index)
209+
cdf.columns = pd.CategoricalIndex(df.columns)
210+
211+
expect = pd.DataFrame(df.ix['A', :], columns=cdf.columns,
212+
index=pd.CategoricalIndex(list('AA')))
213+
assert_frame_equal(cdf.ix['A', :], expect)
214+
215+
expect = pd.DataFrame(df.ix[:, 'X'], index=cdf.index,
216+
columns=pd.CategoricalIndex(list('XX')))
217+
assert_frame_equal(cdf.ix[:, 'X'], expect)
218+
219+
expect = pd.DataFrame(df.ix[['A', 'B'], :], columns=cdf.columns,
220+
index=pd.CategoricalIndex(list('AAB')))
221+
assert_frame_equal(cdf.ix[['A', 'B'], :], expect)
222+
223+
expect = pd.DataFrame(df.ix[:, ['X', 'Y']], index=cdf.index,
224+
columns=pd.CategoricalIndex(list('XXY')))
225+
assert_frame_equal(cdf.ix[:, ['X', 'Y']], expect)
226+
183227
def test_read_only_source(self):
184228
# GH 10043
185229
rw_array = np.eye(10)

0 commit comments

Comments
 (0)