Pandas按指定列分组后按其他列规则筛选取值的更优实现方法
解决方案
场景1:当前问题最优实现
两种简洁写法返回结果均为以date为单级索引的Series,可直接与dayMin拼接使用:
写法1:idxmin直接定位行(性能更高,适合大数据量)
idxmin会返回每组time最小值对应的行索引,直接提取对应value即可:
# 简化写法,直接在apply中返回标量值 dayOpen = df.groupby('date').apply(lambda g: g.loc[g['time'].idxmin(), 'value'])
写法2:排序后取首行(更直观,适合通用排序场景)
先按分组列+排序列升序排列,分组后取每组第一个元素的value:
dayOpen = df.sort_values(['date', 'time']).groupby('date')['value'].first()
如果需要取time最大对应的value,仅需调整排序规则即可:
dayClose = df.sort_values(['date', 'time'], ascending=[True, False]).groupby('date')['value'].first()
场景2:通用需求适配模板
针对你提到的按A列分组、对B列执行过滤或排序操作、提取对应C列取值的通用场景,可直接使用以下模板实现,避免生成多余索引:
result = df.groupby('A列名').apply(lambda group: # 此处编写单个分组的自定义逻辑,最终返回单值即可 group[group['B列名'] > 自定义阈值]['C列名'].mean() # 过滤后聚合示例 # 或排序后取指定位置值:group.sort_values('B列名')['C列名'].iloc[目标位置下标] )
原代码问题说明
你之前的实现返回多余索引,是因为lambda函数返回了筛选后的子DataFrame,groupby.apply会自动将组索引和原表行索引拼接为多级索引。仅需让lambda函数最终返回单个值(如加.iloc[0]提取单个value),即可避免该问题:
# 原代码修改后即可正常使用 dayOpen = df.groupby('date').apply(lambda df: df[ df.time == df.time.min() ]['value'].iloc[0])
内容的提问来源于stack exchange,提问作者Matthew Kozubov
相关产品推荐
相关产品推荐

