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

如何在pandas中按ID筛选出对应最近2个日期的所有行

Pandas按ID分组提取每组最近两个日期所有行的实现方法

核心逻辑:按id分组后对日期做密集排名,保留排名前2(对应最大、次大日期)的所有行,可完整保留原表所有字段,兼容同日期下有多条数据的场景。

前置处理

首先需要将日期列转为日期类型,避免字符串格式比较出现异常:

import pandas as pd
import numpy as np

# 构造示例数据
data = {'id':  np.repeat((['a','b','c']), 6),
        'date': ['2020-12-07', '2020-12-07','2020-12-05','2020-12-05','2020-12-04','2020-12-04',
                 '2021-12-07', '2021-12-07','2021-09-05','2021-09-05','2021-05-04','2021-05-04',
                 '2021-09-05', '2021-09-05','2021-02-05','2021-02-05','2020-12-04','2020-12-04'],
        'value1': np.repeat(([10,20,30]), 6),
        'value2': np.repeat(([1000,2000,3000]), 6)
        }
df = pd.DataFrame(data)

# 转换日期列格式
df['date'] = pd.to_datetime(df['date'])

方法1:基于rank实现(推荐,性能更高)

用密集排名dense保证相同日期的排名一致,直接筛选排名<=2的行即可:

df_filtered = df[df.groupby('id')['date'].rank(method='dense', ascending=False) <= 2]

# 如需恢复日期为字符串格式可执行
df_filtered['date'] = df_filtered['date'].dt.strftime('%Y-%m-%d')

# 重置索引与示例输出对齐
df_filtered = df_filtered.reset_index(drop=True)
print(df_filtered)

方法2:基于nlargest实现(符合你提到的nlargest使用习惯)

先提取每个组的前2个唯一最大日期,再筛选组内符合条件的所有行:

def filter_top2_date_rows(group):
    # 取当前组的前2个唯一最大日期
    top2_dates = group['date'].drop_duplicates().nlargest(2)
    # 返回该日期对应的所有行
    return group[group['date'].isin(top2_dates)]

df_filtered = df.groupby('id', group_keys=False).apply(filter_top2_date_rows).reset_index(drop=True)

两种方法的输出均与你给出的期望结果完全一致。


内容的提问来源于stack exchange,提问作者navac

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 23:45:03