Closed
Description
It would be convenient to have from_product
infer level names from inputs if at all possible.
Current behavior
>>> a = pd.Series([1, 2, 3], name='a')
>>> b = pd.Series(['a', 'b'], name='b')
>>> pd.MultiIndex.from_product([a, b])
MultiIndex(levels=[[1, 2, 3], ['a', 'b']],
codes=[[0, 0, 1, 1, 2, 2], [0, 1, 0, 1, 0, 1]])
Current workaround
>>> arrs = [a, b]
>>> pd.MultiIndex.from_product(ins, names=[el.name for el in arrs])
MultiIndex(levels=[[1, 2, 3], ['a', 'b']],
codes=[[0, 0, 1, 1, 2, 2], [0, 1, 0, 1, 0, 1]],
names=['a', 'b'])
Obviously this would't make sense for lists or arrays being passed in, but in the case of a Series
, it would be nice to have the name persisted.
From glancing at the source, it looks like this would be somewhat simple to implement, the naive approach might be something like:
from pandas.core.arrays.categorical import _factorize_from_iterables
from pandas.core.reshape.util import cartesian_product
if not is_list_like(iterables):
raise TypeError("Input must be a list / sequence of iterables.")
elif is_iterator(iterables):
iterables = list(iterables)
if names is None:
names = [el.name if hasattr(el, 'name') else None for el in iterables]
codes, levels = _factorize_from_iterables(iterables)
codes = cartesian_product(codes)
return MultiIndex(levels, codes, sortorder=sortorder, names=names)