diff --git a/doc/source/whatsnew/v1.4.0.rst b/doc/source/whatsnew/v1.4.0.rst index 450ecc85c725b..14c9626eb6d27 100644 --- a/doc/source/whatsnew/v1.4.0.rst +++ b/doc/source/whatsnew/v1.4.0.rst @@ -325,6 +325,7 @@ MultiIndex - Bug in :meth:`MultiIndex.get_loc` where the first level is a :class:`DatetimeIndex` and a string key is passed (:issue:`42465`) - Bug in :meth:`MultiIndex.reindex` when passing a ``level`` that corresponds to an ``ExtensionDtype`` level (:issue:`42043`) - Bug in :meth:`MultiIndex.get_loc` raising ``TypeError`` instead of ``KeyError`` on nested tuple (:issue:`42440`) +- Bug in :meth:`MultiIndex.putmask` where the other value was also a :class:`MultiIndex` (:issue:`43212`) - I/O diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index 4d80480468adb..c3e5b3f6a6e0b 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -3678,7 +3678,12 @@ def astype(self, dtype, copy: bool = True): return self def _validate_fill_value(self, item): - if not isinstance(item, tuple): + if isinstance(item, MultiIndex): + # GH#43212 + if item.nlevels != self.nlevels: + raise ValueError("Item must have length equal to number of levels.") + return item._values + elif not isinstance(item, tuple): # Pad the key with empty strings if lower levels of the key # aren't specified: item = (item,) + ("",) * (self.nlevels - 1) diff --git a/pandas/tests/indexes/multi/test_putmask.py b/pandas/tests/indexes/multi/test_putmask.py new file mode 100644 index 0000000000000..2a24be9003302 --- /dev/null +++ b/pandas/tests/indexes/multi/test_putmask.py @@ -0,0 +1,17 @@ +import numpy as np + +from pandas import MultiIndex +import pandas._testing as tm + + +def test_putmask_multiindex_other(): + # GH#43212 `value` is also a MultiIndex + + left = MultiIndex.from_tuples([(np.nan, 6), (np.nan, 6), ("a", 4)]) + right = MultiIndex.from_tuples([("a", 1), ("a", 1), ("d", 1)]) + mask = np.array([True, True, False]) + + result = left.putmask(mask, right) + + expected = MultiIndex.from_tuples([right[0], right[1], left[2]]) + tm.assert_index_equal(result, expected)