@@ -3096,17 +3096,19 @@ def reorder_levels(self, order):
3096
3096
def __getslice__ (self , i , j ):
3097
3097
return self .__getitem__ (slice (i , j ))
3098
3098
3099
- def sortlevel (self , level = 0 , ascending = True ):
3099
+ def sortlevel (self , level = 0 , ascending = True , sort_remaining = True ):
3100
3100
"""
3101
3101
Sort MultiIndex at the requested level. The result will respect the
3102
3102
original ordering of the associated factor at that level.
3103
3103
3104
3104
Parameters
3105
3105
----------
3106
- level : int or str, default 0
3106
+ level : list-like, int or str, default 0
3107
3107
If a string is given, must be a name of the level
3108
+ If list-like must be names or ints of levels.
3108
3109
ascending : boolean, default True
3109
3110
False to sort in descending order
3111
+ sort_remaining : sort by the remaining levels after level.
3110
3112
3111
3113
Returns
3112
3114
-------
@@ -3115,24 +3117,35 @@ def sortlevel(self, level=0, ascending=True):
3115
3117
from pandas .core .groupby import _indexer_from_factorized
3116
3118
3117
3119
labels = list (self .labels )
3120
+ shape = list (self .levshape )
3118
3121
3119
- level = self ._get_level_number (level )
3120
- primary = labels .pop (level )
3122
+ if isinstance (level , (str , int )):
3123
+ level = [level ]
3124
+ level = [self ._get_level_number (lev ) for lev in level ]
3121
3125
3122
- shape = list (self .levshape )
3123
- primshp = shape .pop (level )
3126
+ # partition labels and shape
3127
+ primary = tuple (labels .pop (lev - i ) for i , lev in enumerate (level ))
3128
+ primshp = tuple (shape .pop (lev - i ) for i , lev in enumerate (level ))
3124
3129
3125
- indexer = _indexer_from_factorized ((primary ,) + tuple (labels ),
3126
- (primshp ,) + tuple (shape ),
3130
+ if sort_remaining :
3131
+ primary += primary + tuple (labels )
3132
+ primshp += primshp + tuple (shape )
3133
+ sortorder = None
3134
+ else :
3135
+ sortorder = level [0 ]
3136
+
3137
+ indexer = _indexer_from_factorized (primary ,
3138
+ primshp ,
3127
3139
compress = False )
3140
+
3128
3141
if not ascending :
3129
3142
indexer = indexer [::- 1 ]
3130
3143
3131
3144
indexer = com ._ensure_platform_int (indexer )
3132
3145
new_labels = [lab .take (indexer ) for lab in self .labels ]
3133
3146
3134
3147
new_index = MultiIndex (labels = new_labels , levels = self .levels ,
3135
- names = self .names , sortorder = level ,
3148
+ names = self .names , sortorder = sortorder ,
3136
3149
verify_integrity = False )
3137
3150
3138
3151
return new_index , indexer
0 commit comments