You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pandas中实现带条件的聚合列?对应SQL逻辑实现

如何在Pandas中创建带条件的聚合列

你需要实现与以下SQL等价的Pandas逻辑:

SELECT day, 
    SUM(CASE WHEN category = "A" THEN sales ELSE NULL END) / SUM(sales) * 100 AS output_1,
    SUM(CASE WHEN category = "B" AND sex = "female" THEN sales ELSE NULL END) / SUM(sales) * 100 AS output_2
FROM table
GROUP BY 1

源数据表如下:

import pandas as pd

data = {
    'day': ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday', 'Monday'],
    'category': ['A', 'B', 'C', 'A', 'B', 'C', 'A', 'B'],
    'sex': ['male', 'female', 'male', 'female', 'male', 'female', 'male', 'female'],
    'sales': [100, 200, 150, 180, 220, 120, 140, 160]
}
df = pd.DataFrame(data)

预期输出(注:你提供的示例数值与源数据计算结果不符,以下为实际计算产出):

day   output_1    output_2
0     Monday  38.461538   61.538462
1    Tuesday   0.000000  100.000000
2  Wednesday   0.000000    0.000000
3   Thursday  100.000000    0.000000
4     Friday   0.000000    0.000000
5   Saturday   0.000000    0.000000
6     Sunday  100.000000    0.000000

你尝试用.agg()方法实现,但尚未找到正确方案,当前代码框架:

result = (
    df.groupby('column_1')
    .agg(
        output_1(),
        output_2()
    )
    .reset_index()
)

解决方案

方法1:直接使用.agg()结合匿名函数

在.agg()中定义匿名函数,直接完成条件聚合与比例计算:

result = df.groupby('day').agg(
    output_1=lambda x: (x[x['category'] == 'A']['sales'].sum() / x['sales'].sum()) * 100,
    output_2=lambda x: (x[(x['category'] == 'B') & (x['sex'] == 'female')]['sales'].sum() / x['sales'].sum()) * 100
).reset_index()

方法2:先生成条件列再聚合

通过生成临时条件列,让逻辑更直观,适合复杂条件场景:

import numpy as np

# 生成条件匹配的销售额列,不满足条件则为0
df['sales_A'] = np.where(df['category'] == 'A', df['sales'], 0)
df['sales_B_female'] = np.where((df['category'] == 'B') & (df['sex'] == 'female'), df['sales'], 0)
# 获取分组总销售额
df['total_sales'] = df.groupby('day')['sales'].transform('sum')

# 分组计算比例
result = df.groupby('day').agg(
    output_1=lambda x: (x['sales_A'].sum() / x['total_sales'].iloc[0]) * 100,
    output_2=lambda x: (x['sales_B_female'].sum() / x['total_sales'].iloc[0]) * 100
).reset_index()

# 清理临时列(可选)
df.drop(['sales_A', 'sales_B_female', 'total_sales'], axis=1, inplace=True)

方法3:使用assign链式调用简化代码

用assign整合临时列生成与聚合,实现一行链式操作:

result = (
    df.assign(
        sales_A=np.where(df['category'] == 'A', df['sales'], 0),
        sales_B_female=np.where((df['category'] == 'B') & (df['sex'] == 'female'), df['sales'], 0),
        total_sales=lambda x: x.groupby('day')['sales'].transform('sum')
    )
    .groupby('day')
    .agg(
        output_1=lambda x: (x['sales_A'].sum() / x['total_sales'].iloc[0]) * 100,
        output_2=lambda x: (x['sales_B_female'].sum() / x['total_sales'].iloc[0]) * 100
    )
    .reset_index()
)

内容的提问来源于stack exchange,提问作者Andrii Hnoiovyi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 23:32:05