Generating all the combinations of 7 columns in a dataframe and add the corresponding rows to generate new columns

Viewed 364

I have a dataframe that looks similar to below:

Wave    A    B   C
340    77   70  15
341    80   73  15
342    83   76  16
343    86   78  17

I want to generate columns that will have all the possible combinations of the existing columns. I showed 3 cols here but in my actual data, I have 7 columns and therefore 127 total combinations. The desired output is as follows:

Wave    A    B   C   AB   AC   AD   BC ... ABC
340    77   70  15   147  92   ...
341    80   73  15   153  95   ... 
342    83   76  16   159  99   ...

I implemented a quite inefficient version where the user inputs the combinations (AB, AC, etc.) and a new col is created with the sum of the rows. This seems almost impossible to accomplish for 127 combinations, esp with descriptive col names.

2 Answers

Create a list of all combinations with chain + combinations from itertools, then sum the appropriate columns:

from itertools import combinations, chain

cols = [*df.iloc[:,1:]]
l = list(chain.from_iterable(combinations(cols, n+2) for n in range(len(cols))))
#[('A', 'B'), ('A', 'C'), ('B', 'C'), ('A', 'B', 'C')]

for items in l:
    df[''.join(items)] = df.loc[:, items].sum(1)

   Wave   A   B   C   AB   AC  BC  ABC
0   340  77  70  15  147   92  85  162
1   341  80  73  15  153   95  88  168
2   342  83  76  16  159   99  92  175
3   343  86  78  17  164  103  95  181

You need to get the all combination first , then we just get the combination , and we need create the maps dict or Series

l=df.columns[1:].tolist()

l1=[list(map(list, itertools.combinations(l, i))) for i in range(len(l) + 1)]

d=[dict.fromkeys(y,''.join(y))for x in l1 for y in x ]

maps=pd.Series(d).apply(pd.Series).stack()
df.set_index('Wave',inplace=True)
df=df.reindex(columns=maps.index.get_level_values(1))
#here using reindex , get the order of your new df to the maps keys
df.columns=maps.tolist()
# here assign the new value to the column , since the order is same that why here I am assign it back 
df.sum(level=0,axis=1)

Out[303]: 
       A   B   C   AB   AC  BC  ABC
Wave                               
340   77  70  15  147   92  85  162
341   80  73  15  153   95  88  168
342   83  76  16  159   99  92  175
343   86  78  17  164  103  95  181
Related