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

如何用原生Pandas实现SQL的case when计算与分组聚合需求

Pandas原生实现多条件分组统计方案

原始数据集样例

User_id | Search_id | Price | score | clicked | company | rank
1       | 1         | 10    | 7.3   | 0       | other   | 3
1       | 1         | 8     | 10.0  | 1       | other   | 2
1       | 1         | 7.5   | 10.0  | 1       | us      | 1
2       | 2         | 7     | 10.0  | 0       | us      | 3
2       | 2         | 6.5   | 10.0  | 1       | other   | 2
2       | 2         | 4     | 6.5   | 1       | other   | 1

需求逻辑

需要复现如下SQL的计算逻辑:

  1. 先过滤出score=10的数据集
  2. 按User_id、Search_id分组,计算每组clicked=1的最小rank值作为BestClickRank
  3. 再次按User_id、Search_id分组,通过条件判断计算所有要求的统计指标

原始SQL参考:

proc sql;
create table File1_Real as
select User_ID
,      Search_ID  
,      mean(case when company = 'us' then rank else . end) as Our_Rank
,      mean(case when company = 'us' then Price else . end) as Our_Price
,      mean(case when company = 'us' then score else . end) as Our_Score
,      mean(case when company = 'us' then clicked else . end) as Our_Click
,      mean(case when rank <= 5 then price else . end) as Price_Top5
,      mean(case when Rank =  BestClickRank then price else . end) as Top_Price
,      mean(case when Rank =  BestClickRank then case when score= 10 then 1 else 0 end else . end) as Top_is10
,      mean(BestClickRank) as Top_Rank    
,      min(price) as Min_Price
,      count(*) as QuotesReturned
,      sum(case when price < 7.5 then 1 else 0 end) as QuotesLT75
,      mean(case when price < 7.5 then Score else 0 end) as LT75_Score
,      sum(clicked) as TotalClicks
from (
Select *
,      min(case when Clicked = 1 then Rank else . end) as BestClickRank
from work.data
where score = 10
group by user_id, search_id)
Group by 1,2
quit;

预期输出样例

User_id | Search_id | Our_Rank| Our_Price | Our_Score | Our_Click | Price_Top5 | Top_Price | Top_is10 | Top_Rank | Min_Price | QuotesReturned | QuotesLT75 |  LT75_Score | TotalClicks 
1       | 1         | 1       | 7.5       | 10.0      | 1         | 7.75       | 7.5       | 1        | 1        | 7.5       | 2              | 0         | 0           | 2
2       | 2         | 3       | 7         | 10.0      | 0         | 5.8        | 6.5       | 1        | 2        | 6.5       | 2              | 0         | 0           | 1

原生Pandas实现代码

import pandas as pd
import numpy as np

# 1. 过滤符合条件的数据,计算每组BestClickRank
df_filter = df[df['score'] == 10].copy()
df_filter['BestClickRank'] = df_filter.groupby(['User_id', 'Search_id'])['rank'].transform(
    lambda x: x[df_filter.loc[x.index, 'clicked'] == 1].min()
)

# 2. 分组聚合计算所有指标
result = df_filter.groupby(['User_id', 'Search_id'], as_index=False).agg(
    Our_Rank=('rank', lambda x: x[df_filter.loc[x.index, 'company'] == 'us'].mean()),
    Our_Price=('Price', lambda x: x[df_filter.loc[x.index, 'company'] == 'us'].mean()),
    Our_Score=('score', lambda x: x[df_filter.loc[x.index, 'company'] == 'us'].mean()),
    Our_Click=('clicked', lambda x: x[df_filter.loc[x.index, 'company'] == 'us'].mean()),
    Price_Top5=('Price', lambda x: x[df_filter.loc[x.index, 'rank'] <= 5].mean()),
    Top_Price=('Price', lambda x: x[df_filter.loc[x.index, 'rank'] == df_filter.loc[x.index, 'BestClickRank']].mean()),
    Top_is10=('score', lambda x: (x[df_filter.loc[x.index, 'rank'] == df_filter.loc[x.index, 'BestClickRank']] == 10).mean()),
    Top_Rank=('BestClickRank', 'mean'),
    Min_Price=('Price', 'min'),
    QuotesReturned=('User_id', 'count'),
    QuotesLT75=('Price', lambda x: (x < 7.5).sum()),
    LT75_Score=('score', lambda x: x[x < 7.5].mean() if len(x[x < 7.5]) > 0 else 0),
    TotalClicks=('clicked', 'sum')
)

该代码完全使用原生Pandas接口实现,无需额外依赖,计算逻辑与SQL完全对齐,输出结果与预期一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 00:36:04