pandas:为每个索引值和外部列表值的组合创建一行
pandas: create a row per combination of index value and external list value
我正在尝试在数据框中创建一行,该行表示 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
。但它似乎并不能解决问题。我也想过合并列表,但是也没用。
非常感谢您推荐使用的工具!
您还可以使用 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 爆炸函数来做到这一点。
首先使用位置列表填充“位置”列。为此,您需要使用列表理解,否则 pandas 将尝试使用单个列表条目而不是整个列表来填充列的行。列表理解的示例代码如下:
df['Loc'] = [Location for i in range(len(df))]
然后可以使用explode函数拆分 pandas explode函数将列表数据拆分成具有相同“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
您可以使用 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
我正在尝试在数据框中创建一行,该行表示 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
。但它似乎并不能解决问题。我也想过合并列表,但是也没用。
非常感谢您推荐使用的工具!
您还可以使用 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 爆炸函数来做到这一点。
首先使用位置列表填充“位置”列。为此,您需要使用列表理解,否则 pandas 将尝试使用单个列表条目而不是整个列表来填充列的行。列表理解的示例代码如下:
df['Loc'] = [Location for i in range(len(df))]
然后可以使用explode函数拆分 pandas explode函数将列表数据拆分成具有相同“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
您可以使用 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