Skip to content

Commit 8366590

Browse files
committed
BUG: CategoricalIndex allows reindexing with non-unique CategoricalIndex
1 parent 0e7cf48 commit 8366590

File tree

3 files changed

+27
-4
lines changed

3 files changed

+27
-4
lines changed

doc/source/whatsnew/v0.24.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -1018,6 +1018,7 @@ Other API Changes
10181018
- :meth:`Categorical.searchsorted` now raises a ``KeyError`` rather that a ``ValueError``, if a searched for key is not found in its categories (:issue:`23466`).
10191019
- :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`).
10201020
- 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`)
1021+
- :meth:`CategoricalIndex.reindex` now raises a ``ValueError`` in all cases if the target index is non-unique. It previously only raised if the target index was not of a categorical dtype (:issue:`23963`).
10211022

10221023
.. _whatsnew_0240.deprecations:
10231024

pandas/core/indexes/category.py

+8-4
Original file line numberDiff line numberDiff line change
@@ -522,12 +522,16 @@ def reindex(self, target, method=None, level=None, limit=None,
522522

523523
target = ibase.ensure_index(target)
524524

525-
if not is_categorical_dtype(target) and not target.is_unique:
526-
raise ValueError("cannot reindex with a non-unique indexer")
525+
if self.equals(target):
526+
indexer = None
527+
missing = []
528+
else:
529+
if not target.is_unique:
530+
raise ValueError("cannot reindex with a non-unique indexer")
527531

528-
indexer, missing = self.get_indexer_non_unique(np.array(target))
532+
indexer, missing = self.get_indexer_non_unique(np.array(target))
529533

530-
if len(self.codes):
534+
if len(self.codes) and indexer is not None:
531535
new_target = self.take(indexer)
532536
else:
533537
new_target = target

pandas/tests/indexes/test_category.py

+18
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,24 @@ def test_reindex_dtype(self):
540540
tm.assert_numpy_array_equal(indexer,
541541
np.array([0, 3, 2], dtype=np.intp))
542542

543+
def test_reindex_duplicate_target(self):
544+
# See GH23963
545+
c = CategoricalIndex(['a', 'b', 'c', 'a'],
546+
categories=['a', 'b', 'c', 'd'])
547+
with pytest.raises(ValueError, match='non-unique indexer'):
548+
c.reindex(['a', 'a', 'c'])
549+
550+
with pytest.raises(ValueError, match='non-unique indexer'):
551+
c.reindex(CategoricalIndex(['a', 'a', 'c'],
552+
categories=['a', 'b', 'c', 'd']))
553+
554+
# See GH21809
555+
idx = pd.CategoricalIndex(['low'] * 3 + ['hi'] * 3)
556+
dfb = pd.DataFrame(np.random.rand(6, 3), columns=list('abc'), index=idx)
557+
assert dfb.shape == (6, 3)
558+
dfb_round = dfb.round(3)
559+
assert dfb_round.shape == (6, 3)
560+
543561
def test_reindex_empty_index(self):
544562
# See GH16770
545563
c = CategoricalIndex([])

0 commit comments

Comments
 (0)