@@ -3047,7 +3047,9 @@ def maybe_mi_droplevels(indexer, levels):
3047
3047
indexer = self ._get_level_indexer (key , level = level )
3048
3048
return indexer , maybe_mi_droplevels (indexer , [level ])
3049
3049
3050
- def _get_level_indexer (self , key , level : int = 0 , indexer = None ):
3050
+ def _get_level_indexer (
3051
+ self , key , level : int = 0 , indexer : Int64Index | None = None
3052
+ ):
3051
3053
# `level` kwarg is _always_ positional, never name
3052
3054
# return an indexer, boolean array or a slice showing where the key is
3053
3055
# in the totality of values
@@ -3200,10 +3202,12 @@ def get_locs(self, seq):
3200
3202
"MultiIndex slicing requires the index to be lexsorted: slicing "
3201
3203
f"on levels { true_slices } , lexsort depth { self ._lexsort_depth } "
3202
3204
)
3203
- # indexer
3204
- # this is the list of all values that we want to select
3205
+
3205
3206
n = len (self )
3206
- indexer = None
3207
+ # indexer is the list of all positions that we want to take; we
3208
+ # start with it being everything and narrow it down as we look at each
3209
+ # entry in `seq`
3210
+ indexer = Index (np .arange (n ))
3207
3211
3208
3212
def _convert_to_indexer (r ) -> Int64Index :
3209
3213
# return an indexer
@@ -3221,78 +3225,84 @@ def _convert_to_indexer(r) -> Int64Index:
3221
3225
r = r .nonzero ()[0 ]
3222
3226
return Int64Index (r )
3223
3227
3224
- def _update_indexer (idxr : Index | None , indexer : Index | None , key ) -> Index :
3225
- if indexer is None :
3226
- indexer = Index (np .arange (n ))
3227
- if idxr is None :
3228
- return indexer
3228
+ def _update_indexer (idxr : Index , indexer : Index ) -> Index :
3229
3229
indexer_intersection = indexer .intersection (idxr )
3230
3230
if indexer_intersection .empty and not idxr .empty and not indexer .empty :
3231
- raise KeyError (key )
3231
+ raise KeyError (seq )
3232
3232
return indexer_intersection
3233
3233
3234
3234
for i , k in enumerate (seq ):
3235
3235
3236
3236
if com .is_bool_indexer (k ):
3237
3237
# a boolean indexer, must be the same length!
3238
3238
k = np .asarray (k )
3239
- indexer = _update_indexer (
3240
- _convert_to_indexer (k ), indexer = indexer , key = seq
3241
- )
3239
+ lvl_indexer = _convert_to_indexer (k )
3240
+ indexer = _update_indexer (lvl_indexer , indexer = indexer )
3242
3241
3243
3242
elif is_list_like (k ):
3244
3243
# a collection of labels to include from this level (these
3245
3244
# are or'd)
3245
+
3246
3246
indexers : Int64Index | None = None
3247
3247
for x in k :
3248
3248
try :
3249
- idxrs = _convert_to_indexer (
3250
- self ._get_level_indexer (x , level = i , indexer = indexer )
3251
- )
3252
- indexers = (idxrs if indexers is None else indexers ).union (
3253
- idxrs , sort = False
3249
+ # Argument "indexer" to "_get_level_indexer" of "MultiIndex"
3250
+ # has incompatible type "Index"; expected "Optional[Int64Index]"
3251
+ item_lvl_indexer = self ._get_level_indexer (
3252
+ x , level = i , indexer = indexer # type: ignore[arg-type]
3254
3253
)
3255
3254
except KeyError :
3256
-
3257
- # ignore not founds
3255
+ # ignore not founds; see discussion in GH#39424
3258
3256
continue
3257
+ else :
3258
+ idxrs = _convert_to_indexer (item_lvl_indexer )
3259
+
3260
+ if indexers is None :
3261
+ indexers = idxrs
3262
+ else :
3263
+ indexers = indexers .union (idxrs , sort = False )
3259
3264
3260
3265
if indexers is not None :
3261
- indexer = _update_indexer (indexers , indexer = indexer , key = seq )
3266
+ indexer = _update_indexer (indexers , indexer = indexer )
3262
3267
else :
3263
3268
# no matches we are done
3264
- return np .array ([], dtype = np .int64 )
3269
+ # test_loc_getitem_duplicates_multiindex_empty_indexer
3270
+ return np .array ([], dtype = np .intp )
3265
3271
3266
3272
elif com .is_null_slice (k ):
3267
3273
# empty slice
3268
- indexer = _update_indexer ( None , indexer = indexer , key = seq )
3274
+ pass
3269
3275
3270
3276
elif isinstance (k , slice ):
3271
3277
3272
3278
# a slice, include BOTH of the labels
3279
+ # Argument "indexer" to "_get_level_indexer" of "MultiIndex" has
3280
+ # incompatible type "Index"; expected "Optional[Int64Index]"
3281
+ lvl_indexer = self ._get_level_indexer (
3282
+ k ,
3283
+ level = i ,
3284
+ indexer = indexer , # type: ignore[arg-type]
3285
+ )
3273
3286
indexer = _update_indexer (
3274
- _convert_to_indexer (
3275
- self ._get_level_indexer (k , level = i , indexer = indexer )
3276
- ),
3287
+ _convert_to_indexer (lvl_indexer ),
3277
3288
indexer = indexer ,
3278
- key = seq ,
3279
3289
)
3280
3290
else :
3281
3291
# a single label
3292
+ lvl_indexer = self ._get_loc_level (k , level = i )[0 ]
3282
3293
indexer = _update_indexer (
3283
- _convert_to_indexer (self . _get_loc_level ( k , level = i )[ 0 ] ),
3294
+ _convert_to_indexer (lvl_indexer ),
3284
3295
indexer = indexer ,
3285
- key = seq ,
3286
3296
)
3287
3297
3288
3298
# empty indexer
3289
3299
if indexer is None :
3290
- return np .array ([], dtype = np .int64 )
3300
+ return np .array ([], dtype = np .intp )
3291
3301
3292
3302
assert isinstance (indexer , Int64Index ), type (indexer )
3293
3303
indexer = self ._reorder_indexer (seq , indexer )
3294
3304
3295
- return indexer ._values
3305
+ return indexer ._values . astype ( np . intp , copy = False )
3296
3306
3297
3307
# --------------------------------------------------------------------
3298
3308
0 commit comments