Python pandas。如果列值位于第二个数据框的另一个逗号分隔值列中,则需要聚合

Python pandas. Need to aggregate if column value is in another comma separated value column of second dataframe

我有 2 个数据框样本,名称已更改

df1 = 
| Comp_code | DepartmentListA | DepartmentListB |
| --------  | --------------- | --------------- |
| Code_1    | "Dept1"         | "Dept3"         |
| Code_2    | "Dept2"         | "Dept4"         |
| Code_3    | "Dept4, Dept5"  | "Dept1"         |
| Code_4    | "Dept1,Dept5, Dept6"  | "Dept3, Dept4"  |

df2 = 只有部门和收入

| DepartmentList | Revenue|  Gross Margin|
| --------------- | -------| -------|
| "Dept1"         | 1000         | 500
| "Dept2"         | 2000         | 0
| "Dept3,         | 5000         | 900
| "Dept4"         | 5000         | 200
| "Dept5"         | 7000         | -100
| "Dept6"         | 8000         | 2500

我希望我的最终 df 包含公司代码以及总收入和毛利率。汇总 A 列和 B 列中的部门总数。 由于以逗号分隔的部门字符串,我无法迭代和加入。我最后的DF应该是这样的

预期 df =

| Comp_code | GrossRev| Tot Margin|
| --------  | --------------- | --------------- |
| Code_1    | 6000         | 1400         |
| Code_2    | 7000         | 200         |
| Code_3    | 13000  | 600         |
| Code_4    | 26000  | 4000  |

数据框也有几百万行,一些部门列表(逗号分隔值)大约有 100 个。如果有一种高效的方法来做到这一点,那就太好了。

TIA,

您可以通过以下方式做到这一点

df["all"] = ((df["DepartmentListA"] + 
              ", " + 
              df["DepartmentListB"]).str.split("[\s,]+"))

df3 = df.explode("all")

df3 = (pd.merge(df3, df2, left_on='all', 
               right_on='Comp_code', suffixes=('', '_y'))
               .groupby("Comp_code")
                .agg({'Revenue': ['sum'], 'Gross Margin': 'sum'}).reset_index())

df3.columns = df3.columns.droplevel(-1)
print(df3)

  Comp_code  Revenue  Gross Margin
0    Code_1     6000          1400
1    Code_2     7000           200
2    Code_3    13000           600
3    Code_4    26000          4000

您可以 melt+explode 获取每个部门的单独行,然后 mergedf2 获取数据,最后 groupby+ sum 聚合 sum:

(df1.melt(id_vars='Comp_code')
    .assign(value=lambda d: d['value'].str.split(r',\s*'))
    .explode('value')
    .merge(df2, left_on='value', right_on='DepartmentList')
    .groupby('Comp_code').agg({'Revenue': 'sum', 'Gross Margin': 'sum'})
)

输出:

           Revenue  Gross Margin
Comp_code                       
Code_1        6000          1400
Code_2        7000           200
Code_3       13000           600
Code_4       26000          4000