首页 > 解决方案 > 数据框中的所有唯一列组合

问题描述

谢谢阅读。

我正在尝试在 dataframe 中创建所有可能的唯一列组合。因此,具有 A、B、C 和 D 列,组合将是AB、AC、AD、BC、BD、ABC、ABD

A   B   C   D   AB   AC   AD ...
1   1   3   2   2    4    3

为此,我创建了一个 for 循环:

for i, comb in enumerate(df_p.columns):
    for comb2 in df_p.columns[i:]:
        if (comb != comb2) & (comb not in comb2)):
            df_p[comb + ' + ' + comb2] = df_p[comb].astype('str') + ' + ' + df_p[comb2].astype("str")
            print(" comb: " + comb + " combines with comb2: " + comb2)

基本上,“comb”迭代器从第一列 (A) 开始,第二个迭代器“comb2”从第二列 (B) 开始,创建 AB,然后继续前进,直到创建所有 A 组合。然后,当comb 到B 时,comb2 从C 开始,以此类推。if 条件阻止了 A + A 和 A + BA 之类的事情(我在 df 中使用更多列进行测试时遇到了一些错误)。

我现在的问题是关于反向重复,例如当迭代器一位于字母 A 时创建“ABD”(迭代器二将它与所有列组合)以及当迭代器一位于 D 和迭代器二时创建“DBA”所有组合。

在我的研究中,我也尝试过使用 itertools 组合,如下所示:set(itertools.combinations(df_p.columns, 2))对于 2 的组合,对于所有其他可能的组合,以此类推,但后来我遇到了麻烦,将新创建的列组合(如 AB)与行值“映射”我原来的 df (对于这个例子,这将是 A 的行值 + B 的行值)。

我更喜欢 itertools 选项,因为它可以更好地控制我们想要多少组合,并且可能并不难映射。有什么想法吗?

提前致谢。

- - - - - - - - - - - - - - - - - 更新 - - - - - - - - --------------------------

只是为了清楚起见,我忘了提到行是字符串。这是真实列的片段:

retired     nationality     region
   1         Portugal       Lisbon

因此,例如创建这 3 个的所有组合将是:

retired  nationality  region  retired + nationality   retired + region   (..)
   1      Portugal    Lisbon      1 + Portugal           1 + Lisbon

标签: pythonpandascombinationsitertools

解决方案


IIUC,combinationsreduceSeries.add

from itertools import combinations
from functools import reduce

cols = df.columns.copy()
for i in range(2, len(cols) + 1):
    for names in combinations(cols, i):
        df[''.join(names)] = reduce(lambda cum_serie, new_serie_name: \
                                    cum_serie.add(df[new_serie_name]),
                                    names[1:],
                                    df[names[0]])


print(df)

输出

   A  B  C  D  AB  AC  AD  BC  BD  CD  ABC  ABD  ACD  BCD  ABCD
0  1  1  3  2   2   4   3   4   3   5    5    4    6    6     7

编辑

df = df.rename(columns=str).astype(str)
cols = df.columns.copy()
for i in range(2, len(cols) + 1):
    for names in combinations(cols, i):
        df[' + '.join(names)] = reduce(lambda cum_serie, new_serie_name: \
                                    cum_serie.str.cat(df[new_serie_name], ' + '),
                                    names[1:],
                                    df[names[0]])
print(df)

   A  B  C  D  A + B  A + C  A + D  B + C  B + D  C + D  A + B + C  A + B + D  \
0  1  1  3  2  1 + 1  1 + 3  1 + 2  1 + 3  1 + 2  3 + 2  1 + 1 + 3  1 + 1 + 2   

   A + C + D  B + C + D  A + B + C + D  
0  1 + 3 + 2  1 + 3 + 2  1 + 1 + 3 + 2  

推荐阅读