Python:将所有符合约束条件的唯一组合输出到Pandas DataFrame

3

请谅解,因为我正在学习Python,以下是我使用Pandas DataFrame所拥有的工人属性列:姓名,职位和时薪。

df

Index   Name     Position      HourlyPay
  0     John     Analyst         15.00
  1     Mike     Programmer      18.00
  2     Lisa     Supervisor      16.75
  4     Frank    Analyst         15.50

我希望将所有可能的人员组合输出到另一个DataFrame中(如下所示),其中包括他们的职位作为列标题,并有另一列汇总他们的HourlyPay,然后按最高的TotalHourlyPay排序。

uniqueDf

Index   Analyst  Programmer  Supervisor  TotalHourlyPay
 0       Frank      Mike       Lisa          50.25
 1       John       Mike       Lisa          49.75

我在上面的uniqueDf示例中使用了3个位置,但有时会发生变化。例如,2个分析师职位可以同时工作,因此我想要在需要时动态添加或删除多个职位列的选项。下面是第二个示例。

secondExampleDf

Index   Analyst  Analyst Programmer  Supervisor  TotalHourlyPay
 0       Frank    John      Mike       Lisa          65.25

这是一个非常简单的数据集示例,实际上它是更大的数据集的一部分。我尝试解决了这个问题,但我的代码并不值得展示。最接近成功的方法是在df.Name列上使用itertools.combinations。我试图通过在两个 DataFrame之间使用joinmerge来追加和求和一个 TotalHourlyPay 列,但也无法使其正常工作。

possibleCombinations = list(itertools.combinations(df.Name, 3))
uniqueDf = pd.DataFrame(possibleCombinations,columns=['Employee1','Employee2','Employee3'])

我只是想问是否有人能帮我指明方向。我知道SO不是为您编写代码的,这绝对不是我想要的。我真的很困惑接下来该怎么做,Google Chrome上的每个链接都被点击并标记了出来。非常感谢任何帮助。
谢谢
2个回答

1
这段代码可以得到你想要的结果:


import pandas as pd
import itertools

# definition of dataframe
df = pd.DataFrame()
df["Index"] = [0, 1, 2, 4, 5, 6, 8, 9, 10]
df["Name"] = ["John", "Mike", "Lisa", "Franck", "Peter", "Suzanne", "Laura", "Sam", "Manon"]
df["Position"] = ["Analyst", "Programmer", "Supervisor", "Analyst", "Programmer", "Programmer", "Supervisor", "Analyst", "Analyst"]
df["HourlyPay"] = [15.00, 18.00, 16.75, 15.50, 17.00, 18.00, 16.00, 12.00, 13.00]

# dict of dataframes by position
unique_positions = list(df["Position"].unique())
pos_dfs = {}
for pos in unique_positions:
    pos_dfs[pos] = df.loc[df["Position"]==pos].reset_index()

# required positions with count
req_pos_count = pd.DataFrame.from_dict({"count":{"Analyst": 2, "Supervisor": 1, "Programmer": 1}})
req_pos_unique = list(req_pos_count.index.unique())
req_pos_dfs = [pos_dfs[pos] for pos in req_pos_unique]

which_pos = [item for _, row in req_pos_count.iterrows() for item in [row.name]*row["count"]]
which_pos_count = [str(i) + "_" + pos for i, pos in enumerate(which_pos)]

# combinations
pos_dfs_rows = [list(itertools.combinations(range(len(pos_df)), req_pos_count.loc[req_pos_unique[i]]["count"]))
                for i, pos_df in enumerate(req_pos_dfs)]
pos_dfs_rows_comb = [[it for item in sublist for it in item]
                     for sublist in list(itertools.product(*pos_dfs_rows)) ]

# building of result
uniqueDf = pd.DataFrame(index=range(len(pos_dfs_rows_comb)), columns=which_pos_count+["TotalHourlyPay"])
for k, comb in enumerate(pos_dfs_rows_comb):
    rows = [pos_dfs[which_pos[i]].ix[ind] for i, ind in enumerate(comb)]
    tp = pd.concat(rows, axis=1, ignore_index=True).transpose()
    uniqueDf.loc[k, which_pos_count] = list(tp["Name"])
    uniqueDf["TotalHourlyPay"].loc[k] = tp["HourlyPay"].sum()
uniqueDf.sort_values(by="TotalHourlyPay", inplace=True)

这正是我想要达到的目标。非常感谢您在我最初发布错误信息后继续与我合作。我真的很感激,谢谢! - Drew Szurko

0
这是我遵循的过程。 首先,获取职位保留或缺失的指标变量:
position = pd.get_dummies(df['Position']).astype(bool)
not_position = ~pd.get_dummies(df['Position'], prefix='not').astype(bool)
df1 = pd.concat([df, position, not_position], axis=1)

接下来,生成可能的组合:
df2 = df1.merge(df1, left_on='Programmer', right_on='not_Programmer', suffixes=['', '_y'])
df3 = df2.merge(df1, left_on='Supervisor', right_on='not_Supervisor', suffixes=['', '_z'])

然后,删除重复项并提取仍然相关的字段

df4 = df3[(df3['Analyst']) & (df3['Programmer_y']) & (df3['Supervisor_z'])]
df4.loc[:, ['Name', 'Name_y', 'Name_z', 'HourlyPay', 'HourlyPay_y', 'HourlyPay_z']]
    Name Name_y Name_z  HourlyPay  HourlyPay_y  HourlyPay_z
0   John   Mike   Lisa       15.0         18.0        16.75
1  Frank   Mike   Lisa       15.5         18.0        16.75

接下来,您可以沿着行求和,删除新无用的支付列,并将剩余的列重命名,以返回类似于uniqueDf的输出。


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