@@ -1173,98 +1173,98 @@ def from_product(cls, iterables, sortorder=None, names=None):
11731173 labels = cartesian_product (labels )
11741174 return MultiIndex (levels , labels , sortorder = sortorder , names = names )
11751175
1176- def _reconstruct (self , sort = False , remove_unused = False ):
1176+ def sort_monotonic (self ):
11771177 """
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
11821180
11831181 The resulting MultiIndex will have the same outward
11841182 appearance, meaning the same .values and ordering. It will also
11851183 be .equals() to the original.
11861184
1187- Parameters
1188- ----------
1189- sort: boolean, default False
1190- monotonically sort the levels
1191- remove_unused: boolean, default False
1192- remove unsued levels
1193-
11941185 Returns
11951186 -------
1196- new MultiIndex
1187+ MultiIndex
11971188
11981189 """
11991190
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
12081193
12091194 new_levels = []
12101195 new_labels = []
12111196
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 ):
12161198
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
12181203
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 )
12231207
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 )
12271211
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 )
12311214
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 )
12361218
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
12391223
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.
12411227
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
12481231
1249- unused = list (reversed (sorted (set (
1250- np .arange (len (lev ))) - set (uniques ))))
1232+ """
12511233
1252- # new levels are simple
1253- lev = lev . take ( uniques )
1234+ new_levels = []
1235+ new_labels = []
12541236
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 )):
12591239
1260- lab = np .where ( lab > u , lab - 1 , lab )
1240+ uniques = np .sort ( algos . unique ( lab ) )
12611241
1242+ # nothing unused
1243+ if len (uniques ) == len (lev ):
12621244 new_levels .append (lev )
12631245 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 )
12641254
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
12681268
12691269 return MultiIndex (new_levels , new_labels ,
12701270 names = self .names , sortorder = self .sortorder ,
0 commit comments