You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 09:05:14