@@ -1173,98 +1173,98 @@ def from_product(cls, iterables, sortorder=None, names=None):
1173
1173
labels = cartesian_product (labels )
1174
1174
return MultiIndex (levels , labels , sortorder = sortorder , names = names )
1175
1175
1176
- def _reconstruct (self , sort = False , remove_unused = False ):
1176
+ def sort_monotonic (self ):
1177
1177
"""
1178
- create a new MultiIndex from the current to provide either:
1179
- - monotonically sorted items IN the levels
1180
- - removing unused levels (meaning that they are not expressed
1181
- in the labels)
1178
+ create a new MultiIndex from the current to monotonically sorted
1179
+ items IN the levels
1182
1180
1183
1181
The resulting MultiIndex will have the same outward
1184
1182
appearance, meaning the same .values and ordering. It will also
1185
1183
be .equals() to the original.
1186
1184
1187
- Parameters
1188
- ----------
1189
- sort: boolean, default False
1190
- monotonically sort the levels
1191
- remove_unused: boolean, default False
1192
- remove unsued levels
1193
-
1194
1185
Returns
1195
1186
-------
1196
- new MultiIndex
1187
+ MultiIndex
1197
1188
1198
1189
"""
1199
1190
1200
- if sort and remove_unused :
1201
- raise ValueError ("only support one of sort / remove_unused" )
1202
-
1203
- if not (sort or remove_unused ):
1204
- raise ValueError ("must supply one of sort / remove_unsued" )
1205
-
1206
- levels = self .levels
1207
- labels = self .labels
1191
+ if self .is_lexsorted () and self .is_monotonic :
1192
+ return self
1208
1193
1209
1194
new_levels = []
1210
1195
new_labels = []
1211
1196
1212
- if sort :
1213
-
1214
- if self .is_lexsorted () and self .is_monotonic :
1215
- return self
1197
+ for lev , lab in zip (self .levels , self .labels ):
1216
1198
1217
- for lev , lab in zip (levels , labels ):
1199
+ if lev .is_monotonic :
1200
+ new_levels .append (lev )
1201
+ new_labels .append (lab )
1202
+ continue
1218
1203
1219
- if lev .is_monotonic :
1220
- new_levels .append (lev )
1221
- new_labels .append (lab )
1222
- continue
1204
+ # indexer to reorder the levels
1205
+ indexer = lev .argsort ()
1206
+ lev = lev .take (indexer )
1223
1207
1224
- # indexer to reorder the levels
1225
- indexer = lev . argsort ( )
1226
- lev = lev . take ( indexer )
1208
+ # indexer to reorder the labels
1209
+ ri = lib . get_reverse_indexer ( indexer , len ( indexer ) )
1210
+ lab = algos . take_1d ( ri , lab )
1227
1211
1228
- # indexer to reorder the labels
1229
- ri = lib .get_reverse_indexer (indexer , len (indexer ))
1230
- lab = algos .take_1d (ri , lab )
1212
+ new_levels .append (lev )
1213
+ new_labels .append (lab )
1231
1214
1232
- new_levels .append (lev )
1233
- new_labels .append (lab )
1234
-
1235
- elif remove_unused :
1215
+ return MultiIndex (new_levels , new_labels ,
1216
+ names = self .names , sortorder = self .sortorder ,
1217
+ verify_integrity = False )
1236
1218
1237
- changed = np .zeros (self .nlevels , dtype = bool )
1238
- for i , (lev , lab ) in enumerate (zip (levels , labels )):
1219
+ def remove_unused_levels (self ):
1220
+ """
1221
+ create a new MultiIndex from the current that removesing
1222
+ unused levels, meaning that they are not expressed in the labels
1239
1223
1240
- uniques = np .sort (algos .unique (lab ))
1224
+ The resulting MultiIndex will have the same outward
1225
+ appearance, meaning the same .values and ordering. It will also
1226
+ be .equals() to the original.
1241
1227
1242
- # nothing unused
1243
- if len (uniques ) == len (lev ):
1244
- new_levels .append (lev )
1245
- new_labels .append (lab )
1246
- changed [i ] = True
1247
- continue
1228
+ Returns
1229
+ -------
1230
+ MultiIndex
1248
1231
1249
- unused = list (reversed (sorted (set (
1250
- np .arange (len (lev ))) - set (uniques ))))
1232
+ """
1251
1233
1252
- # new levels are simple
1253
- lev = lev . take ( uniques )
1234
+ new_levels = []
1235
+ new_labels = []
1254
1236
1255
- # new labels, we remove the unsued
1256
- # by decrementing the labels for that value
1257
- # prob a better way
1258
- for u in unused :
1237
+ changed = np .zeros (self .nlevels , dtype = bool )
1238
+ for i , (lev , lab ) in enumerate (zip (self .levels , self .labels )):
1259
1239
1260
- lab = np .where ( lab > u , lab - 1 , lab )
1240
+ uniques = np .sort ( algos . unique ( lab ) )
1261
1241
1242
+ # nothing unused
1243
+ if len (uniques ) == len (lev ):
1262
1244
new_levels .append (lev )
1263
1245
new_labels .append (lab )
1246
+ changed [i ] = True
1247
+ continue
1248
+
1249
+ unused = list (reversed (sorted (set (
1250
+ np .arange (len (lev ))) - set (uniques ))))
1251
+
1252
+ # new levels are simple
1253
+ lev = lev .take (uniques )
1264
1254
1265
- # nothing changed
1266
- if not changed .any ():
1267
- return self
1255
+ # new labels, we remove the unsued
1256
+ # by decrementing the labels for that value
1257
+ # prob a better way
1258
+ for u in unused :
1259
+
1260
+ lab = np .where (lab > u , lab - 1 , lab )
1261
+
1262
+ new_levels .append (lev )
1263
+ new_labels .append (lab )
1264
+
1265
+ # nothing changed
1266
+ if not changed .any ():
1267
+ return self
1268
1268
1269
1269
return MultiIndex (new_levels , new_labels ,
1270
1270
names = self .names , sortorder = self .sortorder ,
0 commit comments