diff --git a/pandas/core/generic.py b/pandas/core/generic.py index c052b977ea07a..424041a59f3a9 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -3765,11 +3765,15 @@ class animal locomotion if isinstance(index, MultiIndex): try: - loc, new_index = index._get_loc_level( - key, level=0, drop_level=drop_level - ) + loc, new_index = index._get_loc_level(key, level=0) except TypeError as e: raise TypeError(f"Expected label or tuple of labels, got {key}") from e + else: + if not drop_level: + if lib.is_integer(loc): + new_index = index[loc : loc + 1] + else: + new_index = index[loc] else: loc = index.get_loc(key) diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index 39efc57052bc4..cac0a8cc5791f 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -2931,17 +2931,22 @@ def get_loc_level(self, key, level=0, drop_level: bool = True): level = self._get_level_number(level) else: level = [self._get_level_number(lev) for lev in level] - return self._get_loc_level(key, level=level, drop_level=drop_level) - def _get_loc_level(self, key, level: int | list[int] = 0, drop_level: bool = True): + loc, mi = self._get_loc_level(key, level=level) + if not drop_level: + if lib.is_integer(loc): + mi = self[loc : loc + 1] + else: + mi = self[loc] + return loc, mi + + def _get_loc_level(self, key, level: int | list[int] = 0): """ get_loc_level but with `level` known to be positional, not name-based. """ # different name to distinguish from maybe_droplevels - def maybe_mi_droplevels(indexer, levels, drop_level: bool): - if not drop_level: - return self[indexer] + def maybe_mi_droplevels(indexer, levels): # kludge around orig_index = new_index = self[indexer] @@ -2969,7 +2974,7 @@ def maybe_mi_droplevels(indexer, levels, drop_level: bool): result = loc if result is None else result & loc - return result, maybe_mi_droplevels(result, level, drop_level) + return result, maybe_mi_droplevels(result, level) # kludge for #1796 if isinstance(key, list): @@ -2980,7 +2985,7 @@ def maybe_mi_droplevels(indexer, levels, drop_level: bool): try: if key in self.levels[0]: indexer = self._get_level_indexer(key, level=level) - new_index = maybe_mi_droplevels(indexer, [0], drop_level) + new_index = maybe_mi_droplevels(indexer, [0]) return indexer, new_index except (TypeError, InvalidIndexError): pass @@ -2995,7 +3000,7 @@ def partial_selection(key, indexer=None): ilevels = [ i for i in range(len(key)) if key[i] != slice(None, None) ] - return indexer, maybe_mi_droplevels(indexer, ilevels, drop_level) + return indexer, maybe_mi_droplevels(indexer, ilevels) if len(key) == self.nlevels and self.is_unique: # Complete key in unique index -> standard get_loc @@ -3030,10 +3035,10 @@ def partial_selection(key, indexer=None): if indexer is None: indexer = slice(None, None) ilevels = [i for i in range(len(key)) if key[i] != slice(None, None)] - return indexer, maybe_mi_droplevels(indexer, ilevels, drop_level) + return indexer, maybe_mi_droplevels(indexer, ilevels) else: indexer = self._get_level_indexer(key, level=level) - return indexer, maybe_mi_droplevels(indexer, [level], drop_level) + return indexer, maybe_mi_droplevels(indexer, [level]) def _get_level_indexer(self, key, level: int = 0, indexer=None): # `level` kwarg is _always_ positional, never name @@ -3268,9 +3273,7 @@ def _update_indexer(idxr: Index | None, indexer: Index | None, key) -> Index: else: # a single label indexer = _update_indexer( - _convert_to_indexer( - self.get_loc_level(k, level=i, drop_level=False)[0] - ), + _convert_to_indexer(self._get_loc_level(k, level=i)[0]), indexer=indexer, key=seq, )