我正在努力找到一种有效/ pythonic方式来实现以下目标:
- 对于df中的每一行,在Var1
,Var2
和Var3
之间生成笛卡尔积。
- 笛卡尔积的每个元组都是数据帧中的新行
- 对于每一行,在原始数据框中插入其他列(在我的示例中为Id
和Grp
我知道我可以使用类似list(itertools.product(a, b, c))
的东西来获取笛卡尔积,但我不知道如何在数据框环境中执行此操作。我可以在for循环中执行此操作,但生产数据框可能有超过10万行,因此我首先考虑效率。
使用的Python版本:3.6 +
输入数据帧:
import numpy as np
import pandas as pd
df = pd.DataFrame({'Id': [1,2],
'Grp': ['A','B'],
'Var1': [[11,12],[11,19]],
'Var2': [[0],[20,25]],
'Var3': [[34],[31,35,38]]
})
预期输出(CartesianProduct
或Var1, Var2, Var3
很好,我不需要两者):
CartesianProduct Grp Id Var1 Var2 Var3
0 (11, 0, 34) A 1 11 0 34
1 (12, 0, 34) A 1 12 0 34
2 (11, 20, 31) B 2 11 20 31
3 (11, 20, 35) B 2 11 20 35
4 (11, 20, 38) B 2 11 20 38
5 (11, 25, 31) B 2 11 25 31
6 (11, 25, 35) B 2 11 25 35
7 (11, 25, 38) B 2 11 25 38
8 (19, 20, 31) B 2 19 20 31
9 (19, 20, 35) B 2 19 20 35
10 (19, 20, 38) B 2 19 20 38
11 (19, 25, 31) B 3 19 25 31
12 (19, 25, 35) B 4 19 25 35
13 (19, 25, 38) B 5 19 25 38
答案 0 :(得分:1)
以下是itertools
的一种方式:
import numpy as np
import pandas as pd
from itertools import product, chain
df = pd.DataFrame({'Id': [1,2],
'Grp': ['A','B'],
'Var1': [[11,12],[11,19]],
'Var2': [[0],[20,25]],
'Var3': [[34],[31,35,38]]})
df['Cart'] = [list(product(*x)) for x in df[['Var1','Var2','Var3']].values.tolist()]
lens = list(map(len, df['Cart']))
df_out = pd.DataFrame({'Grp': np.repeat(df['Grp'].values, lens),
'Id': np.repeat(df['Id'].values, lens),
'Cart': list(chain(*df['Cart'].values))})
df_out = df_out.join(pd.DataFrame(df_out['Cart'].tolist(),
columns=['Var1', 'Var2', 'Var3']))
# Cart Grp Id Var1 Var2 Var3
# 0 (11, 0, 34) A 1 11 0 34
# 1 (12, 0, 34) A 1 12 0 34
# 2 (11, 20, 31) B 2 11 20 31
# 3 (11, 20, 35) B 2 11 20 35
# 4 (11, 20, 38) B 2 11 20 38
# 5 (11, 25, 31) B 2 11 25 31
# 6 (11, 25, 35) B 2 11 25 35
# 7 (11, 25, 38) B 2 11 25 38
# 8 (19, 20, 31) B 2 19 20 31
# 9 (19, 20, 35) B 2 19 20 35
# 10 (19, 20, 38) B 2 19 20 38
# 11 (19, 25, 31) B 2 19 25 31
# 12 (19, 25, 35) B 2 19 25 35
# 13 (19, 25, 38) B 2 19 25 38