Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v1.4.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -699,7 +699,7 @@ Indexing
- Bug in indexing on columns with ``loc`` or ``iloc`` using a slice with a negative step with ``ExtensionDtype`` columns incorrectly raising (:issue:`44551`)
- Bug in :meth:`IntervalIndex.get_indexer_non_unique` returning boolean mask instead of array of integers for a non unique and non monotonic index (:issue:`44084`)
- Bug in :meth:`IntervalIndex.get_indexer_non_unique` not handling targets of ``dtype`` 'object' with NaNs correctly (:issue:`44482`)
-
- Bug in :meth:`Series.loc.__setitem__` and :meth:`Series.loc.__getitem__` not raising when using multiple keys without using a :class:`MultiIndex` (:issue:`13831`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah let's move this to 1.5

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, I moved whatsnew


Missing
^^^^^^^
Expand Down
12 changes: 10 additions & 2 deletions pandas/core/indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,7 @@ def _getitem_nested_tuple(self, tup: tuple):
# we are only getting non-hashable tuples, in particular ones
# that themselves contain a slice entry
# See test_loc_series_getitem_too_many_dimensions
raise ValueError("Too many indices")
raise IndexingError("Too many indexers")

# this is a series with a multi-index specified a tuple of
# selectors
Expand Down Expand Up @@ -1231,6 +1231,14 @@ def _convert_to_indexer(self, key, axis: int):
is_int_index = labels.is_integer()
is_int_positional = is_integer(key) and not is_int_index

if (
isinstance(key, tuple)
and not isinstance(labels, MultiIndex)
and self.ndim < 2
and len(key) > 1
):
raise IndexingError("Too many indexers")

if is_scalar(key) or (isinstance(labels, MultiIndex) and is_hashable(key)):
# Otherwise get_loc will raise InvalidIndexError

Expand Down Expand Up @@ -1262,7 +1270,7 @@ def _convert_to_indexer(self, key, axis: int):
if is_nested_tuple(key, labels):
if self.ndim == 1 and any(isinstance(k, tuple) for k in key):
# GH#35349 Raise if tuple in tuple for series
raise ValueError("Too many indices")
raise IndexingError("Too many indexers")
return labels.get_locs(key)

elif is_list_like_indexer(key):
Expand Down
22 changes: 22 additions & 0 deletions pandas/tests/indexing/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
)
import pandas._testing as tm
from pandas.core.api import Float64Index
from pandas.core.indexing import IndexingError
from pandas.tests.indexing.common import _mklbl
from pandas.tests.indexing.test_floats import gen_obj

Expand Down Expand Up @@ -978,3 +979,24 @@ def test_extension_array_cross_section_converts():

result = df.iloc[0]
tm.assert_series_equal(result, expected)


@pytest.mark.parametrize(
"ser, keys",
[(Series([10]), (0, 0)), (Series([1, 2, 3], index=list("abc")), (0, 1))],
)
def test_ser_indexer_exceeds_dimensions(ser, keys, indexer_sli):
# GH#13831
if indexer_sli == tm.setitem:
return

exp_err, exp_msg = IndexingError, "Too many indexers"
with pytest.raises(exp_err, match=exp_msg):
indexer_sli(ser)[keys]

if indexer_sli == tm.iloc:
# For iloc.__setitem__ we let numpy handle the error reporting.
exp_err, exp_msg = IndexError, "too many indices for array"

with pytest.raises(exp_err, match=exp_msg):
indexer_sli(ser)[keys] = 0
18 changes: 15 additions & 3 deletions pandas/tests/indexing/test_loc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2685,6 +2685,18 @@ def test_loc_with_period_index_indexer():
tm.assert_frame_equal(df, df.loc[list(idx)])


def test_loc_setitem_multiindex_timestamp():
# GH#13831
vals = np.random.randn(8, 6)
idx = date_range("1/1/2000", periods=8)
cols = ["A", "B", "C", "D", "E", "F"]
exp = DataFrame(vals, index=idx, columns=cols)
exp.loc[exp.index[1], ("A", "B")] = np.nan
vals[1][0:2] = np.nan
res = DataFrame(vals, index=idx, columns=cols)
tm.assert_frame_equal(res, exp)


def test_loc_getitem_multiindex_tuple_level():
# GH#27591
lev1 = ["a", "b", "c"]
Expand Down Expand Up @@ -2889,11 +2901,11 @@ def test_loc_series_getitem_too_many_dimensions(self, indexer):
index=MultiIndex.from_tuples([("A", "0"), ("A", "1"), ("B", "0")]),
data=[21, 22, 23],
)
msg = "Too many indices"
with pytest.raises(ValueError, match=msg):
msg = "Too many indexers"
with pytest.raises(IndexingError, match=msg):
ser.loc[indexer, :]

with pytest.raises(ValueError, match=msg):
with pytest.raises(IndexingError, match=msg):
ser.loc[indexer, :] = 1

def test_loc_setitem(self, string_series):
Expand Down