Skip to content

Commit e464a88

Browse files
ryanreh99jreback
authored andcommitted
BUG: Raise KeyError when indexing a Series with MultiIndex (#26155)
1 parent 77855a1 commit e464a88

File tree

4 files changed

+22
-1
lines changed

4 files changed

+22
-1
lines changed

doc/source/whatsnew/v0.25.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ Indexing
327327
^^^^^^^^
328328

329329
- Improved exception message when calling :meth:`DataFrame.iloc` with a list of non-numeric objects (:issue:`25753`).
330+
- Bug in :meth:`DataFrame.loc` and :meth:`Series.loc` where ``KeyError`` was not raised for a ``MultiIndex`` when the key was less than or equal to the number of levels in the :class:`MultiIndex` (:issue:`14885`).
330331
- Bug in which :meth:`DataFrame.append` produced an erroneous warning indicating that a ``KeyError`` will be thrown in the future when the data to be appended contains new columns (:issue:`22252`).
331332
-
332333

pandas/core/indexing.py

+6
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,12 @@ def _handle_lowerdim_multi_index_axis0(self, tup):
944944
except TypeError:
945945
# slices are unhashable
946946
pass
947+
except KeyError as ek:
948+
# raise KeyError if number of indexers match
949+
# else IndexingError will be raised
950+
if (len(tup) <= self.obj.index.nlevels
951+
and len(tup) > self.obj.ndim):
952+
raise ek
947953
except Exception as e1:
948954
if isinstance(tup[0], (slice, Index)):
949955
raise IndexingError("Handle elsewhere")

pandas/tests/indexing/multiindex/test_getitem.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ def test_series_getitem_returns_scalar(
8585
@pytest.mark.parametrize('indexer,expected_error,expected_error_msg', [
8686
(lambda s: s.__getitem__((2000, 3, 4)), KeyError, r"^356L?$"),
8787
(lambda s: s[(2000, 3, 4)], KeyError, r"^356L?$"),
88-
(lambda s: s.loc[(2000, 3, 4)], IndexingError, 'Too many indexers'),
88+
(lambda s: s.loc[(2000, 3, 4)], KeyError, r"^356L?$"),
89+
(lambda s: s.loc[(2000, 3, 4, 5)], IndexingError, 'Too many indexers'),
8990
(lambda s: s.__getitem__(len(s)), IndexError, 'index out of bounds'),
9091
(lambda s: s[len(s)], IndexError, 'index out of bounds'),
9192
(lambda s: s.iloc[len(s)], IndexError,

pandas/tests/indexing/multiindex/test_loc.py

+13
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import pandas as pd
88
from pandas import DataFrame, Index, MultiIndex, Series
9+
from pandas.core.indexing import IndexingError
910
from pandas.util import testing as tm
1011

1112

@@ -130,6 +131,18 @@ def test_loc_multiindex(self):
130131
with pytest.raises(KeyError, match=r"^2L?$"):
131132
mi_int.ix[2]
132133

134+
def test_loc_multiindex_too_many_dims(self):
135+
# GH 14885
136+
s = Series(range(8), index=MultiIndex.from_product(
137+
[['a', 'b'], ['c', 'd'], ['e', 'f']]))
138+
139+
with pytest.raises(KeyError, match=r"^\('a', 'b'\)$"):
140+
s.loc['a', 'b']
141+
with pytest.raises(KeyError, match=r"^\('a', 'd', 'g'\)$"):
142+
s.loc['a', 'd', 'g']
143+
with pytest.raises(IndexingError, match='Too many indexers'):
144+
s.loc['a', 'd', 'g', 'j']
145+
133146
def test_loc_multiindex_indexer_none(self):
134147

135148
# GH6788

0 commit comments

Comments
 (0)