From ea3884be6a658c9bf402c30593c3de1c91cd686b Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Mon, 3 Feb 2020 17:20:26 -0600 Subject: [PATCH] Backport PR #31631: REGR: Fixed setitem with MultiIndex --- doc/source/whatsnew/v1.0.1.rst | 1 + pandas/core/indexing.py | 3 ++- pandas/tests/indexing/multiindex/test_setitem.py | 10 ++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.0.1.rst b/doc/source/whatsnew/v1.0.1.rst index 180411afb117d..e0182e4e3c1f2 100644 --- a/doc/source/whatsnew/v1.0.1.rst +++ b/doc/source/whatsnew/v1.0.1.rst @@ -17,6 +17,7 @@ Fixed regressions - Fixed regression in :class:`DataFrame` setting values with a slice (e.g. ``df[-4:] = 1``) indexing by label instead of position (:issue:`31469`) - Fixed regression when indexing a ``Series`` or ``DataFrame`` indexed by ``DatetimeIndex`` with a slice containg a :class:`datetime.date` (:issue:`31501`) +- Fixed regression in ``DataFrame.__setitem__`` raising an ``AttributeError`` with a :class:`MultiIndex` and a non-monotonic indexer (:issue:`31449`) - Fixed regression in :class:`Series` multiplication when multiplying a numeric :class:`Series` with >10000 elements with a timedelta-like scalar (:issue:`31457`) - Fixed regression in :meth:`GroupBy.apply` if called with a function which returned a non-pandas non-scalar object (e.g. a list or numpy array) (:issue:`31441`) - Fixed regression in :meth:`to_datetime` when parsing non-nanosecond resolution datetimes (:issue:`31491`) diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index 5624bb5799104..35909e1693b3f 100755 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -926,7 +926,8 @@ def _setitem_with_indexer(self, indexer, value): # we can directly set the series here # as we select a slice indexer on the mi - idx = index._convert_slice_indexer(idx) + if isinstance(idx, slice): + idx = index._convert_slice_indexer(idx) obj._consolidate_inplace() obj = obj.copy() obj._data = obj._data.setitem(indexer=tuple([idx]), value=value) diff --git a/pandas/tests/indexing/multiindex/test_setitem.py b/pandas/tests/indexing/multiindex/test_setitem.py index aebd1ad2573ed..1e641760f7e8d 100644 --- a/pandas/tests/indexing/multiindex/test_setitem.py +++ b/pandas/tests/indexing/multiindex/test_setitem.py @@ -414,6 +414,16 @@ def test_astype_assignment_with_dups(self): df["A"] = df["A"].astype(np.float64) tm.assert_index_equal(df.index, index) + def test_setitem_nonmonotonic(self): + # https://github.com/pandas-dev/pandas/issues/31449 + index = pd.MultiIndex.from_tuples( + [("a", "c"), ("b", "x"), ("a", "d")], names=["l1", "l2"] + ) + df = pd.DataFrame(data=[0, 1, 2], index=index, columns=["e"]) + df.loc["a", "e"] = np.arange(99, 101, dtype="int64") + expected = pd.DataFrame({"e": [99, 1, 100]}, index=index) + tm.assert_frame_equal(df, expected) + def test_frame_setitem_view_direct(multiindex_dataframe_random_data): # this works because we are modifying the underlying array