pandas按id分组:completion_dt重复时保留Maturity_dt最大行
需求说明
使用pandas处理DataFrame时,需实现如下行筛选逻辑:针对每个id分组,若组内completion_dt字段值存在重复,仅保留重复项中Maturity_dt字段为最大日期的行,删除其余重复行。
- 原始测试数据:
id Maturity_dt score completion_dt 1 2020-12-31 12 2022-06-24 2 2020-12-31 8 2022-03-30 2 2019-12-31 0 2022-03-30 2 2018-12-31 0 2021-08-24 3 2022-12-31 15 2022-05-31 2 2021-12-31 12 2022-05-31
- 期望输出结果:
id Maturity_dt score completion_dt 1 2020-12-31 12 2022-06-24 2 2020-12-31 8 2022-03-30 2 2018-12-31 0 2021-08-24 3 2022-12-31 15 2022-05-31 2 2021-12-31 12 2022-05-31
原有代码问题
原有实现代码如下:
df = df.sort_values('Maturity_dt').drop_duplicates(subset=['completion_dt', 'id'], keep='last')
问题出在两个地方:
- 没有提前将日期列转换为
datetime类型,如果列是字符串格式,极端场景下字符串字典序和真实日期顺序不一致会导致排序错误 - 排序默认采用升序,虽然
keep='last'理论上可以取到同组最大值,但如果存在同组内Maturity_dt为空值、格式异常值的情况,排序逻辑会不符合预期
正确实现方案
运行前先做日期类型转换,规避格式导致的计算异常:
import pandas as pd # 统一转换日期列为datetime类型 df['Maturity_dt'] = pd.to_datetime(df['Maturity_dt']) df['completion_dt'] = pd.to_datetime(df['completion_dt'])
方案1:排序去重法
逻辑直观,性能更好,适合大数据量场景:
# 按Maturity_dt降序排序,同id+completion_dt组的第一行就是Maturity_dt最大的行 df_res = df.sort_values(by='Maturity_dt', ascending=False, ignore_index=True) # 按id和completion_dt联合去重,保留第一条即可 df_res = df_res.drop_duplicates(subset=['id', 'completion_dt'], keep='first')
如果需要保留原始数据的行顺序,去重后可以再按原始索引排序:
df_res = df_res.sort_index()
方案2:分组过滤法
逻辑直白,不需要提前调整行顺序:
# 匹配每行所属id+completion_dt组的最大Maturity_dt,保留值相等的行即可 df_res = df[df.groupby(['id', 'completion_dt'])['Maturity_dt'].transform('max') == df['Maturity_dt']]
两种方案运行后输出结果和期望结果完全一致。
内容的提问来源于stack exchange,提问作者PolarVertex
相关产品推荐
相关产品推荐

