问题描述
我正在尝试在数据框中创建一行,以表示 df
的索引和列表中的值之间的唯一组合。
一个简短的例子比很多词更明确!
Id
0 16342939
1 16346727
和列表
Location = ['DC1','DC2','store1','store2']
我希望实现的是:
Id Loc
0 16342939 DC1
0 16342939 DC2
0 16342939 store1
0 16342939 store2
1 16346727 DC1
1 16346727 DC2
1 16346727 store1
1 16346727 store2
我在问我应该使用什么工具在 python 中做到这一点。我考虑并搜索了 itertools
和 combinations
。但它似乎并没有做到这一点。我也想过合并列表,但是也没用。
对使用工具的推荐将不胜感激!
解决方法
您可以使用列表推导和 Pandas 爆炸函数来做到这一点。
首先用位置列表填充“位置”列。为此,您需要使用列表理解,否则 Pandas 将尝试使用单个列表条目而不是整个列表填充列的行。列表理解的示例代码如下:
df['Loc'] = [Location for i in range(len(df))]
然后您可以使用explode函数拆分pandasexplode函数,将列表数据拆分为具有相同“Id”值的单独行。示例代码如下:
df = df.explode('Loc')
最终结果如下:
Id Loc
0 16342939 DC1
0 16342939 DC2
0 16342939 store1
0 16342939 store2
1 16346727 DC1
1 16346727 DC2
1 16346727 store1
1 16346727 store2
,
您也可以使用 pyjanitor
库中的 expand_grid
others = {"Id": df.Id.array,'Loc': Location}
In [87]: janitor.expand_grid(others = others)
Out[87]:
Id Loc
0 16342939 DC1
1 16342939 DC2
2 16342939 store1
3 16342939 store2
4 16346727 DC1
5 16346727 DC2
6 16346727 store1
7 16346727 store2
你可以用 numpy 获得更快的速度:
left = np.repeat(df.Id.array,len(Location))
right = np.resize(Location,len(df)*len(Location))
combo =zip(['Id','Loc'],map(pd.Series,(left,right)))
pd.concat(dict(combo),axis = 'columns')
Id Loc
0 16342939 DC1
1 16342939 DC2
2 16342939 store1
3 16342939 store2
4 16346727 DC1
5 16346727 DC2
6 16346727 store1
7 16346727 store2
,
您可以使用pandas.DataFrame.merge
:
>>> df.merge(pd.Series(Location,name = 'Loc'),how = "cross")
Id Loc
0 16342939 DC1
1 16342939 DC2
2 16342939 store1
3 16342939 store2
4 16346727 DC1
5 16346727 DC2
6 16346727 store1
7 16346727 store2