聚合后如何有条件地对来自不同列的值求和?

Posted

技术标签:

【中文标题】聚合后如何有条件地对来自不同列的值求和?【英文标题】:How can I conditionally sum values from different columns after aggregation? 【发布时间】:2019-12-12 00:46:31 【问题描述】:

我有这个数据框开始:

ID PRODUCT_ID        NAME  STOCK  SELL_COUNT DELIVERED_BY PRICE_A PRICE_B
1         P1  PRODUCT_P1     12          15          UPS   32,00   40,00
2         P2  PRODUCT_P2      4           3          DHL    8,00     NaN
3         P3  PRODUCT_P3    120          22          DHL     NaN  144,00
4         P1  PRODUCT_P1    423          18          UPS   98,00     NaN
5         P2  PRODUCT_P2      0           5          GLS   12,00   18,00
6         P3  PRODUCT_P3     53          10          DHL   84,00     NaN
7         P4  PRODUCT_P4     22           0          UPS    2,00     NaN
8         P1  PRODUCT_P1     94          56          GLS     NaN   49,00
9         P1  PRODUCT_P1      9          24          GLS     NaN    1,00

我想要实现的是 - 在按 PRODUCT_ID 聚合后,根据 PRICE_A 或 PRICE_B 是否具有值来求和(如果两者都设置,则优先考虑 PRICE_A)。

基于@WeNYoBen 的帮助answer,我现在知道如何根据不同的列有条件地应用聚合函数:

def custom_aggregate(grouped):

    data = 
        'STOCK': grouped.loc[grouped['DELIVERED_BY'] == 'UPS', 'STOCK'].min(),
        'TOTAL_SELL_COUNT': grouped.loc[grouped['ID'] > 6, 'SELL_COUNT'].sum(min_count=1),
        'COND_SELL_COUNT': grouped.loc[grouped['SELL_COUNT'] > 10, 'SELL_COUNT'].sum(min_count=1)
        # THIS IS WHERE THINGS GET FOGGY...
        # I somehow need to add a second condition here, that says 
        # if PRICE_B is set - use the PRICE_B value for the sum()
        'COND_PRICE': grouped.loc[grouped['PRICE_A'].notna(), 'PRICE_A'].sum()
    

    d_series = pd.Series(data)
    return d_series

result = df_products.groupby('PRODUCT_ID').apply(custom_aggregate)

我真的不知道这是否可以通过使用 .loc 函数来实现。 解决此问题的一种方法是在调用 .groupby 之前创建一个附加列,该列已经包含正确的价格值。 但我认为可能有一种更灵活的方式来做到这一点。 我很乐意以某种方式为“COND_PRICE”值计算应用一个自定义函数,该函数在将结果传递给 sum() 之前执行。在 SQL 中,我可以嵌套 x 层 CASE WHEN END 语句以实现这种逻辑。只是好奇如何在 pandas 中实现这种灵活性。

非常感谢。

【问题讨论】:

不确定我是否理解。根据您的输入,您的预期输出是什么? 【参考方案1】:

所以这是我们需要的解决方案fillna

def custom_aggregate(grouped):

    data = 
        'STOCK': grouped.loc[grouped['DELIVERED_BY'] == 'UPS', 'STOCK'].min(),
        'TOTAL_SELL_COUNT': grouped.loc[grouped['ID'] > 6, 'SELL_COUNT'].sum(min_count=1),
        'COND_SELL_COUNT': grouped.loc[grouped['SELL_COUNT'] > 10, 'SELL_COUNT'].sum(min_count=1),
        # Fillna if A have the value A return , if not check with B , both nan will keep the value as nan
        'COND_PRICE': grouped['PRICE_A'].fillna(grouped['PRICE_B']).sum()
    

    d_series = pd.Series(data)
    return d_series

【讨论】:

非常感谢您帮助我(再次!!)。这完全可以完成所要求的工作。但是请你这么好心,给我一个提示,是否可以以某种方式将函数应用于 sum() 之前的部分?您基本上更新了 grouped['PRICE_A'] 中的缺失值。我正在寻找的是一个获取grouped 并应用不同的嵌套条件并检查每个分组行的函数,以便“构建” sum() 的动态值。 @user2549803 您可以通过 np.where 进行检查

以上是关于聚合后如何有条件地对来自不同列的值求和?的主要内容,如果未能解决你的问题,请参考以下文章

如何对不同列的值求和

如何聚合数据框并通过 r 中的重复行对列的值求和

根据不同的条件对两个不同的列进行分组和求和

如何在不同条件下聚合两个不同列中的值?

在给定特定条件 SQL 的情况下,仅对不同的值求和

SQL使用group by获取SUM,但有条件地对两列之一的内容求和