在pandas中查找三列可能的唯一组合

4

我试图在pandas中找到三个变量列的所有可能组合。示例数据框如下:

          Variable_Name Variable1 Variable2 Variable3
0                  X      6.0%      8.0%     10.0%
1                  Y      3.0%      4.0%      5.0%
2                  Z      1.0%      3.0%      5.0%

这些组合必须只从该列中取值,不能将值移动到其他列中,例如使用4.0%作为“X”将是不正确的。

尝试使用itertools.combinationsitertools.productitertools.permutation,但这些结果会给出所有可能的组合。

我想要的结果应该像这样,给出27个可能的组合:

     Y      X     Z
0   3.0%   6.0%  1.0%
1   3.0%   6.0%  3.0%
2   3.0%   6.0%  5.0%
3   3.0%   8.0%  1.0%
4   3.0%   8.0%  3.0%
5   3.0%   8.0%  5.0%
6   3.0%  10.0%  1.0%
7   3.0%  10.0%  3.0%
8   3.0%  10.0%  5.0%
9   4.0%   8.0%  3.0%
10  4.0%   8.0%  1.0%
11  4.0%   8.0%  5.0%
12  4.0%   6.0%  1.0%
13  4.0%   6.0%  3.0%
14  4.0%   6.0%  5.0%
15  4.0%  10.0%  1.0%
16  4.0%  10.0%  3.0%
17  4.0%  10.0%  5.0%
18  5.0%  10.0%  5.0%
19  5.0%  10.0%  1.0%
20  5.0%  10.0%  3.0%
21  5.0%   8.0%  1.0%
22  5.0%   8.0%  3.0%
23  5.0%   8.0%  5.0%
24  5.0%   6.0%  1.0%
25  5.0%   6.0%  3.0%
26  5.0%   6.0%  5.0%

任何帮助都将不胜感激。


@HenryEcker 这是一个错误,已经被更正了。 - R_Sengupta
2个回答

1
让我们尝试逐步交叉合并每个变量的值:
from functools import reduce

import pandas as pd

df = pd.DataFrame({'Variable_Name': {0: 'X', 1: 'Y', 2: 'Z'},
                   'Variable1': {0: '6.0%', 1: '3.0%', 2: '1.0%'},
                   'Variable2': {0: '8.0%', 1: '4.0%', 2: '3.0%'},
                   'Variable3': {0: '10.0%', 1: '5.0%', 2: '5.0%'}})

# Save Var Names for later
var_names = df['Variable_Name']

# Get Variables Options in Own Rows
new_df = df.set_index('Variable_Name').stack() \
    .droplevel(1, 0) \
    .reset_index()

# Get Collection of DataFrames each with its own variable
dfs = tuple(new_df[new_df['Variable_Name'].eq(v)]
            .drop(columns=['Variable_Name']) for v in var_names)
# Successive Cross Merges
new_df = reduce(lambda left, right: pd.merge(left, right, how='cross'), dfs)
# Fix Column Names
new_df.columns = var_names
# Fix Axis Names
new_df = new_df.rename_axis(None, axis=1)

# For Display
print(new_df.to_string())

输出:

         X     Y     Z
0     6.0%  3.0%  1.0%
1     6.0%  3.0%  3.0%
2     6.0%  3.0%  5.0%
3     6.0%  4.0%  1.0%
4     6.0%  4.0%  3.0%
5     6.0%  4.0%  5.0%
6     6.0%  5.0%  1.0%
7     6.0%  5.0%  3.0%
8     6.0%  5.0%  5.0%
9     8.0%  3.0%  1.0%
10    8.0%  3.0%  3.0%
11    8.0%  3.0%  5.0%
12    8.0%  4.0%  1.0%
13    8.0%  4.0%  3.0%
14    8.0%  4.0%  5.0%
15    8.0%  5.0%  1.0%
16    8.0%  5.0%  3.0%
17    8.0%  5.0%  5.0%
18   10.0%  3.0%  1.0%
19   10.0%  3.0%  3.0%
20   10.0%  3.0%  5.0%
21   10.0%  4.0%  1.0%
22   10.0%  4.0%  3.0%
23   10.0%  4.0%  5.0%
24   10.0%  5.0%  1.0%
25   10.0%  5.0%  3.0%
26   10.0%  5.0%  5.0%

0
你可以使用CROSS JOIN。在pandas中,你可以使用pd.merge()pd.DataFrame.join()函数,并设置参数how='cross'来实现交叉连接。但在进行交叉连接之前,你需要将每个变量放入一个长格式(未旋转)的数据框中(你的表格是宽格式(旋转)的)。
df_X = df.loc[df['Variable_Name'] == 'X', ['Variable1', 'Variable2', 'Variable3']].T
df_Y = df.loc[df['Variable_Name'] == 'Y', ['Variable1', 'Variable2', 'Variable3']].T
df_Z = df.loc[df['Variable_Name'] == 'Z', ['Variable1', 'Variable2', 'Variable3']].T

cross_join_df = df_X.join(df_Y, how='cross').join(df_Z, how='cross')
cross_join_df.columns = ['X','Y','Z']

如果你需要在循环中使用这个代码,就应该像这样。

variables = df['Variable_Name'].unique()
columns_to_cross = ['Variable1', 'Variable2', 'Variable3']
cross_join_df = df.loc[df['Variable_Name'] == variables[0], columns_to_cross].T
for var in variables[1:]:
    to_join_df = df.loc[df['Variable_Name'] == var, columns_to_cross].T
    cross_join_df = pd.merge(cross_join_df, to_join_df, how='cross')
cross_join_df.columns = variables

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接