@@ -3014,17 +3014,19 @@ def reorder_levels(self, order):
3014
3014
def __getslice__ (self , i , j ):
3015
3015
return self .__getitem__ (slice (i , j ))
3016
3016
3017
- def sortlevel (self , level = 0 , ascending = True ):
3017
+ def sortlevel (self , level = 0 , ascending = True , sort_remaining = True ):
3018
3018
"""
3019
3019
Sort MultiIndex at the requested level. The result will respect the
3020
3020
original ordering of the associated factor at that level.
3021
3021
3022
3022
Parameters
3023
3023
----------
3024
- level : int or str, default 0
3024
+ level : list-like, int or str, default 0
3025
3025
If a string is given, must be a name of the level
3026
+ If list-like must be names or ints of levels.
3026
3027
ascending : boolean, default True
3027
3028
False to sort in descending order
3029
+ sort_remaining : sort by the remaining levels after level.
3028
3030
3029
3031
Returns
3030
3032
-------
@@ -3033,24 +3035,35 @@ def sortlevel(self, level=0, ascending=True):
3033
3035
from pandas .core .groupby import _indexer_from_factorized
3034
3036
3035
3037
labels = list (self .labels )
3038
+ shape = list (self .levshape )
3036
3039
3037
- level = self ._get_level_number (level )
3038
- primary = labels .pop (level )
3040
+ if isinstance (level , (str , int )):
3041
+ level = [level ]
3042
+ level = [self ._get_level_number (lev ) for lev in level ]
3039
3043
3040
- shape = list (self .levshape )
3041
- primshp = shape .pop (level )
3044
+ # partition labels and shape
3045
+ primary = tuple (labels .pop (lev - i ) for i , lev in enumerate (level ))
3046
+ primshp = tuple (shape .pop (lev - i ) for i , lev in enumerate (level ))
3042
3047
3043
- indexer = _indexer_from_factorized ((primary ,) + tuple (labels ),
3044
- (primshp ,) + tuple (shape ),
3048
+ if sort_remaining :
3049
+ primary += primary + tuple (labels )
3050
+ primshp += primshp + tuple (shape )
3051
+ sortorder = None
3052
+ else :
3053
+ sortorder = level [0 ]
3054
+
3055
+ indexer = _indexer_from_factorized (primary ,
3056
+ primshp ,
3045
3057
compress = False )
3058
+
3046
3059
if not ascending :
3047
3060
indexer = indexer [::- 1 ]
3048
3061
3049
3062
indexer = com ._ensure_platform_int (indexer )
3050
3063
new_labels = [lab .take (indexer ) for lab in self .labels ]
3051
3064
3052
3065
new_index = MultiIndex (labels = new_labels , levels = self .levels ,
3053
- names = self .names , sortorder = level ,
3066
+ names = self .names , sortorder = sortorder ,
3054
3067
verify_integrity = False )
3055
3068
3056
3069
return new_index , indexer
0 commit comments