如何在Python的df.groupby.agg()中按条件对单列应用函数
问题
主要使用R语言,目前正在提升Python数据分析技能。在R中可通过dplyr的group_by()+summarize(),直接在汇总阶段按条件对列计算(比如按type的不同取值计算duration的均值),还能基于新生成的列继续操作。但在Python中使用df.groupby().agg()实现类似逻辑时遇到困难,希望不提前过滤数据集,直接在agg()内生成多个条件计算的列。
R实现示例
library(dplyr) df %>% group_by(user_id) %>% summarize(avg_parking_duration = mean(duration[type == "parking"]), avg_reservation_duration = mean(duration[type == "reservation"]) )
尝试的Python代码(未实现条件筛选)
df.groupby('user_id').agg( avg_parking_duration = ('duration','mean') ) # 或 df.groupby('user_id').agg( avg_parking_duration = ('duration',lambda x: x.mean()) )
测试数据集
import pandas as pd u1, u2 = 'user1', 'user2' data = {'user_id': [u1, u1,u1,u1, u2, u2,u2,u2], 'type': ['parking', 'parking', 'reservation', 'reservation','parking', 'parking', 'reservation', 'reservation'], 'duration': [43,60,20,23,143,290,25,15]} df = pd.DataFrame.from_dict(data)
解决方案
方法1:在agg()中使用带条件的Lambda函数
直接在agg()里针对每个目标列编写Lambda,利用分组后的DataFrame片段关联type列做条件筛选:
df.groupby('user_id').agg( avg_parking_duration=lambda x: x[x['type'] == 'parking']['duration'].mean(), avg_reservation_duration=lambda x: x[x['type'] == 'reservation']['duration'].mean() )
这里Lambda的参数x是分组后的完整DataFrame片段,因此可以直接通过列名访问type和duration,完成条件过滤后计算均值。
方法2:用assign()生成标记列后聚合(可读性更高)
先通过assign()添加两个标记列,将不符合条件的行设为NaN,再分组聚合求均值(mean()默认忽略NaN):
df.assign( parking_duration=lambda x: x['duration'].where(x['type'] == 'parking'), reservation_duration=lambda x: x['duration'].where(x['type'] == 'reservation') ).groupby('user_id').agg( avg_parking_duration=('parking_duration', 'mean'), avg_reservation_duration=('reservation_duration', 'mean') )
方法3:用pivot_table一步实现
如果仅需按user_id分组、按type统计duration均值,pivot_table更简洁,最后重命名列即可匹配R的输出格式:
pd.pivot_table(df, index='user_id', columns='type', values='duration', aggfunc='mean').rename( columns={'parking': 'avg_parking_duration', 'reservation': 'avg_reservation_duration'} ).reset_index()
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

