Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUG: Raise KeyError when indexing a Series with MultiIndex #26155

Merged
merged 17 commits into from
Apr 26, 2019
Merged
1 change: 1 addition & 0 deletions doc/source/whatsnew/v0.25.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ Indexing
^^^^^^^^

- Improved exception message when calling :meth:`DataFrame.iloc` with a list of non-numeric objects (:issue:`25753`).
- 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`).
- 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`).
-

Expand Down
6 changes: 6 additions & 0 deletions pandas/core/indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,12 @@ def _handle_lowerdim_multi_index_axis0(self, tup):
except TypeError:
# slices are unhashable
pass
except KeyError as ek:
# raise KeyError if number of indexers match
# else IndexingError will be raised
if (len(tup) <= self.obj.index.nlevels
and len(tup) > self.obj.ndim):
raise ek
except Exception as e1:
if isinstance(tup[0], (slice, Index)):
raise IndexingError("Handle elsewhere")
ryanreh99 marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
3 changes: 2 additions & 1 deletion pandas/tests/indexing/multiindex/test_getitem.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ def test_series_getitem_returns_scalar(
@pytest.mark.parametrize('indexer,expected_error,expected_error_msg', [
(lambda s: s.__getitem__((2000, 3, 4)), KeyError, r"^356L?$"),
(lambda s: s[(2000, 3, 4)], KeyError, r"^356L?$"),
(lambda s: s.loc[(2000, 3, 4)], IndexingError, 'Too many indexers'),
(lambda s: s.loc[(2000, 3, 4)], KeyError, r"^356L?$"),
(lambda s: s.loc[(2000, 3, 4, 5)], IndexingError, 'Too many indexers'),
(lambda s: s.__getitem__(len(s)), IndexError, 'index out of bounds'),
(lambda s: s[len(s)], IndexError, 'index out of bounds'),
(lambda s: s.iloc[len(s)], IndexError,
Expand Down
13 changes: 13 additions & 0 deletions pandas/tests/indexing/multiindex/test_loc.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import pandas as pd
from pandas import DataFrame, Index, MultiIndex, Series
from pandas.core.indexing import IndexingError
from pandas.util import testing as tm


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

def test_loc_multiindex_too_many_dims(self):
# GH 14885
s = Series(range(8), index=MultiIndex.from_product(
ryanreh99 marked this conversation as resolved.
Show resolved Hide resolved
[['a', 'b'], ['c', 'd'], ['e', 'f']]))

with pytest.raises(KeyError, match=r"^\('a', 'b'\)$"):
s.loc['a', 'b']
with pytest.raises(KeyError, match=r"^\('a', 'd', 'g'\)$"):
s.loc['a', 'd', 'g']
with pytest.raises(IndexingError, match='Too many indexers'):
s.loc['a', 'd', 'g', 'j']

def test_loc_multiindex_indexer_none(self):

# GH6788
Expand Down