SAS/SQL用户求助:如何用Pandas高效实现多输出分组
在Pandas中高效复现SQL分组聚合逻辑
直接用Pandas的groupby+agg链式调用就能实现,无需提前创建中间列,完美匹配你的SQL逻辑:
import pandas as pd # 假设你的数据存储在DataFrame df中 result = ( # 对应SQL的WHERE region NOT IN ('A') df[df['region'] != 'A'] .groupby( [ 'region', # 对应SQL里的CASE WHEN分组逻辑,pd.cut比嵌套判断更简洁 pd.cut(df['age'], bins=[-float('inf'), 5, 10, float('inf')], labels=['Low', 'Middle', 'High']) ], as_index=False # 让分组列作为普通列输出,和SQL结果结构一致 ) .agg( total=('profit', 'size'), # sum(1)等价于统计行数,size比count更高效 profit=('profit', 'sum'), avg_profit=('profit', lambda x: x.sum() / x.size), max_revenue=('revenue', 'max') # 修正SQL里的"max revenue"为合法列名max_revenue ) )
关键细节说明:
- 过滤条件:
df[df['region'] != 'A']直接对应SQL的WHERE子句,如果你更习惯SQL语法,也可以用df.query("region != 'A'")。 - 分组逻辑:
- 用
pd.cut替代CASE WHEN,代码更简洁易维护;如果一定要严格匹配CASE WHEN的写法,也可以替换成:
直接放到groupby的列表里即可。df['age'].apply(lambda x: 'Low' if x <5 else ('Middle' if 5<=x<=10 else 'High'))
- 用
- 聚合操作:
agg方法支持直接映射列名和聚合函数,和SQL的AS子句一一对应;avg_profit通过lambda表达式直接计算,避免额外的中间计算步骤;size()用于统计分组行数,等价于SQL里的sum(1),比count()更高效(不会排除空值)。
如果你的Pandas版本≥1.3.0,还可以用命名聚合语法,写法和SQL的SELECT列表几乎一致,对SQL用户更友好:
result = ( df.query("region != 'A'") .groupby( [ 'region', pd.cut(df['age'], bins=[-float('inf'),5,10,float('inf')], labels=['Low','Middle','High']) ], as_index=False ) .agg( total=pd.NamedAgg(column='profit', aggfunc='size'), profit=pd.NamedAgg(column='profit', aggfunc='sum'), avg_profit=pd.NamedAgg(column='profit', aggfunc=lambda x: x.sum()/x.size), max_revenue=pd.NamedAgg(column='revenue', aggfunc='max') ) )
整个过程全程链式调用,没有多余的合并或中间列创建,既简洁又高效。
内容的提问来源于stack exchange,提问作者Mobix
相关产品推荐
相关产品推荐

