@@ -99,8 +99,9 @@ def get_indexer_indexer(
99
99
na_position = na_position ,
100
100
)
101
101
elif isinstance (target , ABCMultiIndex ):
102
+ codes = [lev .codes for lev in target ._get_codes_for_sorting ()]
102
103
indexer = lexsort_indexer (
103
- target . codes , orders = ascending , na_position = na_position , codes_given = True
104
+ codes , orders = ascending , na_position = na_position , codes_given = True
104
105
)
105
106
else :
106
107
# Check monotonic-ness before sort an index (GH 11080)
@@ -298,22 +299,8 @@ def decons_obs_group_ids(
298
299
return [lab [indexer ].astype (np .intp , subok = False , copy = True ) for lab in labels ]
299
300
300
301
301
- def indexer_from_factorized (
302
- labels , shape : Shape , compress : bool = True
303
- ) -> npt .NDArray [np .intp ]:
304
- ids = get_group_index (labels , shape , sort = True , xnull = False )
305
-
306
- if not compress :
307
- ngroups = (ids .size and ids .max ()) + 1
308
- else :
309
- ids , obs = compress_group_index (ids , sort = True )
310
- ngroups = len (obs )
311
-
312
- return get_group_index_sorter (ids , ngroups )
313
-
314
-
315
302
def lexsort_indexer (
316
- keys : list [ArrayLike ] | list [ Series ],
303
+ keys : Sequence [ArrayLike | Index | Series ],
317
304
orders = None ,
318
305
na_position : str = "last" ,
319
306
key : Callable | None = None ,
@@ -324,9 +311,9 @@ def lexsort_indexer(
324
311
325
312
Parameters
326
313
----------
327
- keys : list [ArrayLike] | list[ Series]
328
- Sequence of ndarrays to be sorted by the indexer
329
- list [Series] is only if key is not None.
314
+ keys : Sequence [ArrayLike | Index | Series]
315
+ Sequence of arrays to be sorted by the indexer
316
+ Sequence [Series] is only if key is not None.
330
317
orders : bool or list of booleans, optional
331
318
Determines the sorting order for each element in keys. If a list,
332
319
it must be the same length as keys. This determines whether the
@@ -346,83 +333,38 @@ def lexsort_indexer(
346
333
"""
347
334
from pandas .core .arrays import Categorical
348
335
349
- labels = []
350
- shape = []
336
+ if na_position not in ["last" , "first" ]:
337
+ raise ValueError (f"invalid na_position: { na_position } " )
338
+
351
339
if isinstance (orders , bool ):
352
340
orders = [orders ] * len (keys )
353
341
elif orders is None :
354
342
orders = [True ] * len (keys )
355
343
356
- # error: Incompatible types in assignment (expression has type
357
- # "List[Union[ExtensionArray, ndarray[Any, Any], Index, Series]]", variable
358
- # has type "Union[List[Union[ExtensionArray, ndarray[Any, Any]]], List[Series]]")
359
- keys = [ensure_key_mapped (k , key ) for k in keys ] # type: ignore[assignment]
344
+ labels = []
360
345
361
346
for k , order in zip (keys , orders ):
362
- if na_position not in ["last" , "first" ]:
363
- raise ValueError (f"invalid na_position: { na_position } " )
364
-
347
+ k = ensure_key_mapped (k , key )
365
348
if codes_given :
366
- mask = k == - 1
367
- codes = k .copy ()
368
- n = len (codes )
369
- mask_n = n
370
- # error: Item "ExtensionArray" of "Union[Any, ExtensionArray,
371
- # ndarray[Any, Any]]" has no attribute "any"
372
- if mask .any (): # type: ignore[union-attr]
373
- n -= 1
374
-
349
+ codes = cast (np .ndarray , k )
350
+ n = codes .max () + 1 if len (codes ) else 0
375
351
else :
376
352
cat = Categorical (k , ordered = True )
353
+ codes = cat .codes
377
354
n = len (cat .categories )
378
- codes = cat .codes .copy ()
379
- mask = cat .codes == - 1
380
- if mask .any ():
381
- mask_n = n + 1
382
- else :
383
- mask_n = n
384
-
385
- if order : # ascending
386
- if na_position == "last" :
387
- # error: Argument 1 to "where" has incompatible type "Union[Any,
388
- # ExtensionArray, ndarray[Any, Any]]"; expected
389
- # "Union[_SupportsArray[dtype[Any]],
390
- # _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float,
391
- # complex, str, bytes, _NestedSequence[Union[bool, int, float,
392
- # complex, str, bytes]]]"
393
- codes = np .where (mask , n , codes ) # type: ignore[arg-type]
394
- elif na_position == "first" :
395
- # error: Incompatible types in assignment (expression has type
396
- # "Union[Any, int, ndarray[Any, dtype[signedinteger[Any]]]]",
397
- # variable has type "Union[Series, ExtensionArray, ndarray[Any, Any]]")
398
- # error: Unsupported operand types for + ("ExtensionArray" and "int")
399
- codes += 1 # type: ignore[operator,assignment]
400
- else : # not order means descending
401
- if na_position == "last" :
402
- # error: Unsupported operand types for - ("int" and "ExtensionArray")
403
- # error: Argument 1 to "where" has incompatible type "Union[Any,
404
- # ExtensionArray, ndarray[Any, Any]]"; expected
405
- # "Union[_SupportsArray[dtype[Any]],
406
- # _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float,
407
- # complex, str, bytes, _NestedSequence[Union[bool, int, float,
408
- # complex, str, bytes]]]"
409
- codes = np .where (
410
- mask , n , n - codes - 1 # type: ignore[operator,arg-type]
411
- )
412
- elif na_position == "first" :
413
- # error: Unsupported operand types for - ("int" and "ExtensionArray")
414
- # error: Argument 1 to "where" has incompatible type "Union[Any,
415
- # ExtensionArray, ndarray[Any, Any]]"; expected
416
- # "Union[_SupportsArray[dtype[Any]],
417
- # _NestedSequence[_SupportsArray[dtype[Any]]], bool, int, float,
418
- # complex, str, bytes, _NestedSequence[Union[bool, int, float,
419
- # complex, str, bytes]]]"
420
- codes = np .where (mask , 0 , n - codes ) # type: ignore[operator,arg-type]
421
-
422
- shape .append (mask_n )
355
+
356
+ mask = codes == - 1
357
+
358
+ if na_position == "last" and mask .any ():
359
+ codes = np .where (mask , n , codes )
360
+
361
+ # not order means descending
362
+ if not order :
363
+ codes = np .where (mask , codes , n - codes - 1 )
364
+
423
365
labels .append (codes )
424
366
425
- return indexer_from_factorized (labels , tuple ( shape ) )
367
+ return np . lexsort (labels [:: - 1 ] )
426
368
427
369
428
370
def nargsort (
0 commit comments