From 3bfb243eb23e9c76a9b99544fa654b37cff60975 Mon Sep 17 00:00:00 2001 From: phofl Date: Sun, 24 Jan 2021 13:17:15 +0100 Subject: [PATCH 1/2] ERR: Improve error message for Series.loc.getitem with too many dimensions --- doc/source/whatsnew/v1.3.0.rst | 1 + pandas/core/indexing.py | 5 +++++ pandas/tests/indexing/test_loc.py | 12 ++++++++++++ 3 files changed, 18 insertions(+) diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index 381a05a18b278..8a1a8bd43bb4f 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -53,6 +53,7 @@ Other enhancements - :meth:`DataFrame.apply` can now accept non-callable DataFrame properties as strings, e.g. ``df.apply("size")``, which was already the case for :meth:`Series.apply` (:issue:`39116`) - :meth:`Series.apply` can now accept list-like or dictionary-like arguments that aren't lists or dictionaries, e.g. ``ser.apply(np.array(["sum", "mean"]))``, which was already the case for :meth:`DataFrame.apply` (:issue:`39140`) - :meth:`.Styler.set_tooltips` allows on hover tooltips to be added to styled HTML dataframes. +- :meth:`Series.loc.__getitem__` with :class:`MultiIndex` now raising helpful error message when indexer has too many dimensions (:issue:`35349`) .. --------------------------------------------------------------------------- diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index 998a34ce834ea..ce9611dd8f81d 100644 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -846,6 +846,11 @@ def _getitem_nested_tuple(self, tup: Tuple): if self.name != "loc": # This should never be reached, but lets be explicit about it raise ValueError("Too many indices") + if isinstance(self.obj, ABCSeries) and any( + isinstance(k, tuple) for k in tup + ): + # GH#35349 Raise if tuple in tuple for series + raise ValueError("Too many indices") if self.ndim == 1 or not any(isinstance(x, slice) for x in tup): # GH#10521 Series should reduce MultiIndex dimensions instead of # DataFrame, IndexingError is not raised when slice(None,None,None) diff --git a/pandas/tests/indexing/test_loc.py b/pandas/tests/indexing/test_loc.py index aec5e3adfe111..bb0af380f56a4 100644 --- a/pandas/tests/indexing/test_loc.py +++ b/pandas/tests/indexing/test_loc.py @@ -17,6 +17,7 @@ DataFrame, DatetimeIndex, Index, + IndexSlice, MultiIndex, Series, SparseDtype, @@ -2130,3 +2131,14 @@ def test_loc_iloc_setitem_with_listlike(self, size, array_fn): ser = Series(0, index=list("abcde"), dtype=object) ser.iloc[0] = arr tm.assert_series_equal(ser, expected) + + @pytest.mark.parametrize("indexer", [IndexSlice["A", :], ("A", slice(None))]) + def test_loc_series_getitem_too_many_dimensions(self, indexer): + # GH#35349 + ser = Series( + index=MultiIndex.from_tuples([("A", "0"), ("A", "1"), ("B", "0")]), + data=[21, 22, 23], + ) + msg = "Too many indices" + with pytest.raises(ValueError, match=msg): + ser.loc[indexer, :] From 4b8d9102890406d479d03232785c7e2adc0b63c4 Mon Sep 17 00:00:00 2001 From: phofl Date: Sun, 24 Jan 2021 22:39:06 +0100 Subject: [PATCH 2/2] Add setitem case --- doc/source/whatsnew/v1.3.0.rst | 2 +- pandas/core/indexing.py | 5 +++++ pandas/tests/indexing/test_loc.py | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index 8a1a8bd43bb4f..ce0bea74e2ceb 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -53,7 +53,7 @@ Other enhancements - :meth:`DataFrame.apply` can now accept non-callable DataFrame properties as strings, e.g. ``df.apply("size")``, which was already the case for :meth:`Series.apply` (:issue:`39116`) - :meth:`Series.apply` can now accept list-like or dictionary-like arguments that aren't lists or dictionaries, e.g. ``ser.apply(np.array(["sum", "mean"]))``, which was already the case for :meth:`DataFrame.apply` (:issue:`39140`) - :meth:`.Styler.set_tooltips` allows on hover tooltips to be added to styled HTML dataframes. -- :meth:`Series.loc.__getitem__` with :class:`MultiIndex` now raising helpful error message when indexer has too many dimensions (:issue:`35349`) +- :meth:`Series.loc.__getitem__` and :meth:`Series.loc.__setitem__` with :class:`MultiIndex` now raising helpful error message when indexer has too many dimensions (:issue:`35349`) .. --------------------------------------------------------------------------- diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index ce9611dd8f81d..9185098ad48bf 100644 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -1208,6 +1208,11 @@ def _convert_to_indexer(self, key, axis: int, is_setter: bool = False): return {"key": key} if is_nested_tuple(key, labels): + if isinstance(self.obj, ABCSeries) and any( + isinstance(k, tuple) for k in key + ): + # GH#35349 Raise if tuple in tuple for series + raise ValueError("Too many indices") return labels.get_locs(key) elif is_list_like_indexer(key): diff --git a/pandas/tests/indexing/test_loc.py b/pandas/tests/indexing/test_loc.py index bb0af380f56a4..b6e4c38ef7f0e 100644 --- a/pandas/tests/indexing/test_loc.py +++ b/pandas/tests/indexing/test_loc.py @@ -2142,3 +2142,6 @@ def test_loc_series_getitem_too_many_dimensions(self, indexer): msg = "Too many indices" with pytest.raises(ValueError, match=msg): ser.loc[indexer, :] + + with pytest.raises(ValueError, match=msg): + ser.loc[indexer, :] = 1