将DataFrame行与包含列表的多个列之间的笛卡尔积相乘

时间:2018-03-07 09:30:15

标签: python pandas

我正在努力找到一种有效/ pythonic方式来实现以下目标:
  - 对于df中的每一行,在Var1Var2Var3之间生成笛卡尔积。
  - 笛卡尔积的每个元组都是数据帧中的新行   - 对于每一行,在原始数据框中插入其他列(在我的示例中为IdGrp 我知道我可以使用类似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]]
        })

预期输出(CartesianProductVar1, 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

1 个答案:

答案 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