diff --git a/doc/source/whatsnew/v1.4.0.rst b/doc/source/whatsnew/v1.4.0.rst index f18b3b75ca3d2..9acf0b7b884e6 100644 --- a/doc/source/whatsnew/v1.4.0.rst +++ b/doc/source/whatsnew/v1.4.0.rst @@ -413,6 +413,7 @@ Interval Indexing ^^^^^^^^ +- Bug in :meth:`Series.rename` when index in Series is MultiIndex and level in rename is provided. (:issue:`43659`) - Bug in :meth:`DataFrame.truncate` and :meth:`Series.truncate` when the object's Index has a length greater than one but only one unique value (:issue:`42365`) - Bug in :meth:`Series.loc` and :meth:`DataFrame.loc` with a :class:`MultiIndex` when indexing with a tuple in which one of the levels is also a tuple (:issue:`27591`) - Bug in :meth:`Series.loc` when with a :class:`MultiIndex` whose first level contains only ``np.nan`` values (:issue:`42055`) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 5c4f24f2d2aac..bb19438793482 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -1147,7 +1147,11 @@ def rename( # GH 13473 if not callable(replacements): - indexer = ax.get_indexer_for(replacements) + if ax._is_multi and level is not None: + indexer = ax.get_level_values(level).get_indexer_for(replacements) + else: + indexer = ax.get_indexer_for(replacements) + if errors == "raise" and len(indexer[indexer == -1]): missing_labels = [ label diff --git a/pandas/tests/series/methods/test_rename.py b/pandas/tests/series/methods/test_rename.py index eacafa9310384..e00e9a894d340 100644 --- a/pandas/tests/series/methods/test_rename.py +++ b/pandas/tests/series/methods/test_rename.py @@ -4,6 +4,7 @@ from pandas import ( Index, + MultiIndex, Series, ) import pandas._testing as tm @@ -101,3 +102,26 @@ def test_rename_callable(self): tm.assert_series_equal(result, expected) assert result.name == expected.name + + def test_rename_series_with_multiindex(self): + # issue #43659 + arrays = [ + ["bar", "baz", "baz", "foo", "qux"], + ["one", "one", "two", "two", "one"], + ] + + index = MultiIndex.from_arrays(arrays, names=["first", "second"]) + s = Series(np.ones(5), index=index) + result = s.rename(index={"one": "yes"}, level="second", errors="raise") + + arrays_expected = [ + ["bar", "baz", "baz", "foo", "qux"], + ["yes", "yes", "two", "two", "yes"], + ] + + index_expected = MultiIndex.from_arrays( + arrays_expected, names=["first", "second"] + ) + series_expected = Series(np.ones(5), index=index_expected) + + tm.assert_series_equal(result, series_expected)