@@ -1162,6 +1162,11 @@ def from_arrays(cls, arrays, sortorder=None, names=None):
11621162 MultiIndex.from_product : Make a MultiIndex from cartesian product
11631163 of iterables
11641164 """
1165+ if not is_list_like (arrays ):
1166+ raise TypeError ("Input must be a list / sequence of array-likes." )
1167+ elif is_iterator (arrays ):
1168+ arrays = list (arrays )
1169+
11651170 # Check if lengths of all arrays are equal or not,
11661171 # raise ValueError, if not
11671172 for i in range (1 , len (arrays )):
@@ -1206,6 +1211,11 @@ def from_tuples(cls, tuples, sortorder=None, names=None):
12061211 MultiIndex.from_product : Make a MultiIndex from cartesian product
12071212 of iterables
12081213 """
1214+ if not is_list_like (tuples ):
1215+ raise TypeError ('Input must be a list /sequence of tuple-likes.' )
1216+ elif is_iterator (tuples ):
1217+ tuples = list (tuples )
1218+
12091219 if len (tuples ) == 0 :
12101220 if names is None :
12111221 msg = 'Cannot infer number of levels from empty list'
@@ -1260,6 +1270,11 @@ def from_product(cls, iterables, sortorder=None, names=None):
12601270 from pandas .core .categorical import _factorize_from_iterables
12611271 from pandas .core .reshape .util import cartesian_product
12621272
1273+ if not is_list_like (iterables ):
1274+ raise TypeError ("Input must be a list / sequence of iterables." )
1275+ elif is_iterator (iterables ):
1276+ iterables = list (iterables )
1277+
12631278 labels , levels = _factorize_from_iterables (iterables )
12641279 labels = cartesian_product (labels )
12651280 return MultiIndex (levels , labels , sortorder = sortorder , names = names )
@@ -1365,29 +1380,31 @@ def remove_unused_levels(self):
13651380 new_labels = []
13661381
13671382 changed = False
1368- for lev , lab in zip (self .levels , self .labels ):
1383+ for idx , (lev , lab ) in enumerate (zip (self .levels , self .labels )):
1384+ na_idxs = np .where (lab == - 1 )[0 ]
1385+
1386+ if len (na_idxs ):
1387+ lab = np .delete (lab , na_idxs )
13691388
13701389 uniques = algos .unique (lab )
1371- na_idx = np .where (uniques == - 1 )[0 ]
13721390
13731391 # nothing unused
1374- if len (uniques ) != len (lev ) + len ( na_idx ) :
1392+ if len (uniques ) != len (lev ):
13751393 changed = True
13761394
1377- if len (na_idx ):
1378- # Just ensure that -1 is in first position:
1379- uniques [[0 , na_idx [0 ]]] = uniques [[na_idx [0 ], 0 ]]
1380-
13811395 # labels get mapped from uniques to 0:len(uniques)
1382- # -1 (if present) is mapped to last position
1383- label_mapping = np .zeros (len (lev ) + len (na_idx ))
1384- # ... and reassigned value -1:
1385- label_mapping [uniques ] = np .arange (len (uniques )) - len (na_idx )
1396+ label_mapping = np .zeros (len (lev ))
1397+ label_mapping [uniques ] = np .arange (len (uniques ))
13861398
13871399 lab = label_mapping [lab ]
13881400
13891401 # new levels are simple
1390- lev = lev .take (uniques [len (na_idx ):])
1402+ lev = lev .take (uniques )
1403+
1404+ if len (na_idxs ):
1405+ lab = np .insert (lab , na_idxs - np .arange (len (na_idxs )), - 1 )
1406+ else :
1407+ lab = self .labels [idx ]
13911408
13921409 new_levels .append (lev )
13931410 new_labels .append (lab )
0 commit comments