在 pandas 数据框中创建新列作为其他列的总和排列

Creating new columns in pandas dataframe as summed permutations of other columns

希望这个简单的解释能够理解我正在尝试做的事情。假设我有一个 Pandas 数据框,其中包含以下列:

A B C D E
1 2 4 6 4 
3 4 1 2 3
4 7 4 1 4

有谁知道我可以在 table 中创建一组新的列的方法(无需手动操作),对列的排列子集求和?我一直在进行一些搜索,但没有任何运气,因为这是一个相当具体的查询。

例如,如果我想要 5 列中 3 列子集的总和的所有组合 - 一些额外的行可能如下所示:

ABC ACE BDE
  7   9  12
  8   7   9
 15  12  12

...等等(在这种情况下会有 5C3 = 10 行 - 但我实际上正在查看 7C4 示例)

提前致谢!

使用 combinations 代替 permutations 并将元组的每个值加在一起:

from itertools import combinations

cc = list(combinations(df.columns,3))
df = pd.concat([df.loc[:, c].sum(axis=1) for c in cc], axis=1, keys=cc)
df.columns = df.columns.map(''.join)
print (df)
   ABC  ABD  ABE  ACD  ACE  ADE  BCD  BCE  BDE  CDE
0    7    9    7   11    9   11   12   10   12   14
1    8    9   10    6    7    8    7    8    9    6
2   15   12   15    9   12    9   12   15   12    9

或者作为替代:

import itertools
    
pd.DataFrame({'{}{}{}'.format(a, b, c): df[a] + df[b] + df[c] 
              for a, b, c in itertools.combinations(df.columns, 3)})

输出:

   ABC  ABD  ABE  ACD  ACE  ADE  BCD  BCE  BDE  CDE
0    7    9    7   11    9   11   12   10   12   14
1    8    9   10    6    7    8    7    8    9    6
2   15   12   15    9   12    9   12   15   12    9

使用底层 numpy 数组提高效率。

from itertools import combinations

a = df.to_numpy()
df2 = pd.DataFrame(np.vstack([a[:,list(c)].sum(1)
                              for c in combinations(range(df.shape[1]), 3)
                              ]).T,
                   columns=map(''.join, combinations(df, 3))
                   )

输出:

   ABC  ABD  ABE  ACD  ACE  ADE  BCD  BCE  BDE  CDE
0    7    9    7   11    9   11   12   10   12   14
1    8    9   10    6    7    8    7    8    9    6
2   15   12   15    9   12    9   12   15   12    9

注意。这比其他基于 pandas 的解决方案快 运行 ~10 倍。

因为觉得很有意思,所以比较了三个方案


耶斯莱尔

%%timeit

df = pd.DataFrame({"A":[1,3,4],
                  "B":[2,4,7],
                  "C":[4,1,4],
                  "D":[6,2,1],
                  "E":[4,3,4]})

cc = list(combinations(df.columns,3))
df = pd.concat([df.loc[:, c].sum(axis=1) for c in cc], axis=1, keys=cc)
df.columns = df.columns.map(''.join)
df

结果: 5.99 ms ± 20.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)


莫兹威

%%timeit

df = pd.DataFrame({"A":[1,3,4],
                  "B":[2,4,7],
                  "C":[4,1,4],
                  "D":[6,2,1],
                  "E":[4,3,4]})
    
a = df.to_numpy()
df2 = pd.DataFrame(np.vstack([a[:,list(c)].sum(1)
                              for c in combinations(range(df.shape[1]), 3)
                              ]).T,
                   columns=map(''.join, combinations(df, 3))
                   )
df2

结果: 458 µs ± 868 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)


Marco_CH

%%timeit

df = pd.DataFrame({"A":[1,3,4],
                  "B":[2,4,7],
                  "C":[4,1,4],
                  "D":[6,2,1],
                  "E":[4,3,4]})
    
df = pd.DataFrame({'{}{}{}'.format(a, b, c): df[a] + df[b] + df[c] 
              for a, b, c in itertools.combinations(df.columns, 3)})
df

结果: 2.25 ms ± 14.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)


因此,如果性能是关键,那么 mozways 解决方案是迄今为止最好的。如果性能不是那么重要,那么我们可以针对每种偏好提供三种不同的方法:-)