如何在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
相关产品推荐
相关产品推荐

