如何基于groupby最大值快速筛选DataFrame保留目标行?
高效筛选DataFrame:保留单日职业变动记录中序号最大的行
问题背景
我有一个存储人员职业变动历史的大型DataFrame,部分人员单日存在多条变动记录,每条记录都分配了一个Transaction Sequence Number(交易序号)。需要保留每个员工单日里该序号数值最大的行。目前用for循环实现,但效率极低:
list_indexes_to_drop = [] for (associate_id, date), df in df_job_his.groupby(["Employee ID", "Event Date"]): if len(df) > 1: list_indexes_to_drop += list(df.index[df["Transaction Sequence Number"] != df["Transaction Sequence Number"].max()])
我还写了这段代码,但不知道如何用它来筛选DataFrame:
df_job_his.groupby(["Employee ID", "Event Date"])["Transaction Sequence Number"].max()
有没有更高效的实现方式?
示例数据
df_job_his = pd.DataFrame({ "Employee ID": [1, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 6, 7, 8, 9, 9, 10], "Event Date": ["2020-04-05", "2020-06-08", "2020-06-08", "2022-09-01", "2022-02-15", "2022-02-15", "2021-07-29", "2021-07-29", "2021-08-14", "2021-09-14", "2022-01-04", "2022-01-04", "2022-01-04", "2022-04-04", "2020-08-13", "2020-08-13", "2020-03-17"], "Transaction Sequence Number": [1, 1, 2, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1] })
高效解决方案
方法1:groupby + idxmax 直接筛选索引
idxmax会返回每个分组内目标字段最大值对应的行索引,直接用这些索引筛选原DataFrame即可,这是最简洁高效的方式:
# 获取每个(员工ID, 事件日期)分组中交易序号最大的行的索引 max_seq_indexes = df_job_his.groupby(["Employee ID", "Event Date"])["Transaction Sequence Number"].idxmax() # 筛选出目标行 result_df = df_job_his.loc[max_seq_indexes]
注意:如果同一分组内有多行的交易序号同为最大值,
idxmax只会保留第一个出现的行。
方法2:transform 标记分组最大值
通过transform将分组内的最大值广播到该组的每一行,再筛选出序号等于最大值的行:
# 新增列存储当前分组的最大交易序号 df_job_his['group_max_seq'] = df_job_his.groupby(["Employee ID", "Event Date"])["Transaction Sequence Number"].transform('max') # 筛选符合条件的行并删除临时列 result_df = df_job_his[df_job_his["Transaction Sequence Number"] == df_job_his["group_max_seq"]].drop(columns='group_max_seq')
这种方式可以保留同一分组内所有交易序号为最大值的行,适合存在并列最大值的场景。
方法3:rank 筛选排名第一的行
如果需要明确处理并列最大值的情况,可以用rank给分组内的序号排名,再筛选排名第一的行:
# 按分组对交易序号降序排名,相同值取相同排名(min方法保证并列值都为第1名) df_job_his['seq_rank'] = df_job_his.groupby(["Employee ID", "Event Date"])["Transaction Sequence Number"].rank(method='min', ascending=False) # 筛选排名为1的行并删除临时列 result_df = df_job_his[df_job_his['seq_rank'] == 1].drop(columns='seq_rank')
原循环效率低的原因
Pandas的for循环遍历分组属于逐行迭代,没有利用Pandas内置的向量化运算优化,在处理大型DataFrame时会产生大量的性能开销。上述方案均基于Pandas的向量化分组操作,能大幅提升处理速度。
内容的提问来源于stack exchange,提问作者MKJ
相关产品推荐
相关产品推荐

