我以以下数据框开头:
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之前创建一个已经包含正确价格值的附加列。 但是我认为可能会有一种更灵活的方法。 我很乐意以某种方式将自定义函数应用于将结果传递给sum()之前要执行的'COND_PRICE'值计算。在SQL中,我可以嵌套x个级别的CASE WHEN END语句,以实现这种逻辑。只是好奇如何在熊猫中实现这种灵活性。
非常感谢。
答案 0 :(得分:2)
这是我们需要的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