@@ -2591,7 +2591,7 @@ def _partial_tup_index(self, tup, side="left"):
2591
2591
for k , (lab , lev , labs ) in enumerate (zipped ):
2592
2592
section = labs [start :end ]
2593
2593
2594
- if lab not in lev :
2594
+ if lab not in lev and not isna ( lab ) :
2595
2595
if not lev .is_type_compatible (lib .infer_dtype ([lab ], skipna = False )):
2596
2596
raise TypeError ("Level type mismatch: %s" % lab )
2597
2597
@@ -2601,13 +2601,45 @@ def _partial_tup_index(self, tup, side="left"):
2601
2601
loc -= 1
2602
2602
return start + section .searchsorted (loc , side = side )
2603
2603
2604
- idx = lev . get_loc ( lab )
2604
+ idx = self . _get_loc_single_level_index_wrapper ( lev , lab )
2605
2605
if k < n - 1 :
2606
2606
end = start + section .searchsorted (idx , side = "right" )
2607
2607
start = start + section .searchsorted (idx , side = "left" )
2608
2608
else :
2609
2609
return start + section .searchsorted (idx , side = side )
2610
2610
2611
+ def _get_loc_single_level_index_wrapper (self , level_index : Index , key ) -> int :
2612
+ """
2613
+ Wrapper function for MultiIndex.
2614
+ If key is NA value, location of index unify as -1.
2615
+
2616
+ Parameters
2617
+ ----------
2618
+ level_index: Index
2619
+ Single level index in MultiIndex
2620
+ key : label
2621
+
2622
+ Returns
2623
+ -------
2624
+ loc : int
2625
+ If key is NA value, loc is -1
2626
+ Else, location of key in index
2627
+
2628
+ See Also
2629
+ --------
2630
+ Index.get_loc : The get_loc method for (single-level) index.
2631
+
2632
+ Notes
2633
+ -----
2634
+ Depending on Index type, Handling NA value is different using get_loc.
2635
+ But in MultiIndex, NA values is denoted as missing by -1.
2636
+ """
2637
+
2638
+ if is_scalar (key ) and isna (key ):
2639
+ return - 1
2640
+ else :
2641
+ return level_index .get_loc (key )
2642
+
2611
2643
def get_loc (self , key , method = None ):
2612
2644
"""
2613
2645
Get location for a label or a tuple of labels as an integer, slice or
@@ -2707,7 +2739,9 @@ def _maybe_to_slice(loc):
2707
2739
loc = np .arange (start , stop , dtype = "int64" )
2708
2740
2709
2741
for i , k in enumerate (follow_key , len (lead_key )):
2710
- mask = self .codes [i ][loc ] == self .levels [i ].get_loc (k )
2742
+ mask = self .codes [i ][loc ] == self ._get_loc_single_level_index_wrapper (
2743
+ self .levels [i ], k
2744
+ )
2711
2745
if not mask .all ():
2712
2746
loc = loc [mask ]
2713
2747
if not len (loc ):
@@ -2934,8 +2968,7 @@ def convert_indexer(start, stop, step, indexer=indexer, codes=level_codes):
2934
2968
return slice (i , j , step )
2935
2969
2936
2970
else :
2937
-
2938
- code = level_index .get_loc (key )
2971
+ code = self ._get_loc_single_level_index_wrapper (level_index , key )
2939
2972
2940
2973
if level > 0 or self .lexsort_depth == 0 :
2941
2974
# Desired level is not sorted
0 commit comments