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

Make MultiIndex.get_loc raise for unhashable type #35914

Merged
merged 2 commits into from
Sep 5, 2020
Merged

Make MultiIndex.get_loc raise for unhashable type #35914

merged 2 commits into from
Sep 5, 2020

Conversation

dsaxton
Copy link
Member

@dsaxton dsaxton commented Aug 27, 2020

@@ -2721,8 +2723,7 @@ def _maybe_to_slice(loc):
mask[loc] = True
return mask

if not isinstance(key, (tuple, list)):
# not including list here breaks some indexing, xref #30892
Copy link
Member Author

Choose a reason for hiding this comment

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

I think it is okay to remove this comment since we're not actually checking for list here, or should it be moved? cc @jbrockmendel

Copy link
Member

Choose a reason for hiding this comment

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

i think youre right (though havent checked 30892)

@@ -2707,6 +2707,8 @@ def get_loc(self, key, method=None):
"currently supported for MultiIndex"
)

hash(key)
Copy link
Member

Choose a reason for hiding this comment

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

should this raise InvalidIndexError?

Copy link
Member Author

Choose a reason for hiding this comment

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

That was my original thought, but it broke an existing test because evidently passing a singleton list with only np.nan raises the unhashable type error (it hits a line that uses this approach of trying to hash the key):

import numpy as np
import pandas as pd

idx = pd.MultiIndex.from_tuples([("a", 1), ("b", 2)])
idx.get_loc([np.nan])
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-40dd73c454ae> in <module>
----> 1 idx.get_loc([np.nan])

~/opt/miniconda3/envs/pandas-1.1.1/lib/python3.8/site-packages/pandas/core/indexes/multi.py in get_loc(self, key, method)
   2717         lead_key, follow_key = key[:i], key[i:]
   2718         start, stop = (
-> 2719             self.slice_locs(lead_key, lead_key) if lead_key else (0, len(self))
   2720         )
   2721

~/opt/miniconda3/envs/pandas-1.1.1/lib/python3.8/site-packages/pandas/core/indexes/multi.py in slice_locs(self, start, end, step, kind)
   2578         # This function adds nothing to its parent implementation (the magic
   2579         # happens in get_slice_bound method), but it adds meaningful doc.
-> 2580         return super().slice_locs(start, end, step, kind=kind)
   2581
   2582     def _partial_tup_index(self, tup, side="left"):

~/opt/miniconda3/envs/pandas-1.1.1/lib/python3.8/site-packages/pandas/core/indexes/base.py in slice_locs(self, start, end, step, kind)
   5159         start_slice = None
   5160         if start is not None:
-> 5161             start_slice = self.get_slice_bound(start, "left", kind)
   5162         if start_slice is None:
   5163             start_slice = 0

~/opt/miniconda3/envs/pandas-1.1.1/lib/python3.8/site-packages/pandas/core/indexes/multi.py in get_slice_bound(self, label, side, kind)
   2522         if not isinstance(label, tuple):
   2523             label = (label,)
-> 2524         return self._partial_tup_index(label, side=side)
   2525
   2526     def slice_locs(self, start=None, end=None, step=None, kind=None):

~/opt/miniconda3/envs/pandas-1.1.1/lib/python3.8/site-packages/pandas/core/indexes/multi.py in _partial_tup_index(self, tup, side)
   2593             section = labs[start:end]
   2594
-> 2595             if lab not in lev and not isna(lab):
   2596                 if not lev.is_type_compatible(lib.infer_dtype([lab], skipna=False)):
   2597                     raise TypeError(f"Level type mismatch: {lab}")

~/opt/miniconda3/envs/pandas-1.1.1/lib/python3.8/site-packages/pandas/core/indexes/base.py in __contains__(self, key)
   4063         False
   4064         """
-> 4065         hash(key)
   4066         try:
   4067             return key in self._engine

TypeError: unhashable type: 'list'

@dsaxton dsaxton added MultiIndex Regression Functionality that used to work in a prior pandas version labels Aug 27, 2020
@jreback jreback added this to the 1.1.2 milestone Sep 5, 2020
Copy link
Contributor

@jreback jreback left a comment

Choose a reason for hiding this comment

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

lgtm merge on green.

@dsaxton dsaxton merged commit ce6882f into pandas-dev:master Sep 5, 2020
@dsaxton dsaxton deleted the get_loc-unhashable-argument branch September 5, 2020 21:18
@simonjayhawkins
Copy link
Member

@meeseeksdev backport 1.1.x

meeseeksmachine pushed a commit to meeseeksmachine/pandas that referenced this pull request Sep 6, 2020
simonjayhawkins pushed a commit that referenced this pull request Sep 6, 2020
…#36163)

Co-authored-by: Daniel Saxton <2658661+dsaxton@users.noreply.github.com>
jbrockmendel pushed a commit to jbrockmendel/pandas that referenced this pull request Sep 8, 2020
kesmit13 pushed a commit to kesmit13/pandas that referenced this pull request Nov 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
MultiIndex Regression Functionality that used to work in a prior pandas version
Projects
None yet
Development

Successfully merging this pull request may close these issues.

BUG: MultiIndex assignment via loc
4 participants