如何筛选DataFrame中每年每个ID记录数≤3的行?
如何筛选DataFrame中每个ID每年记录数≤3的行?
问题背景
现有一个包含ID和Date列的DataFrame,Date列类型为datetime64[ns],示例数据如下:
ID Date 1 26.04.2011 1 21.10.2011 14 25.02.2010 14 08.07.2010 14 20.10.2010 14 07.01.2011 14 20.04.2011 14 02.07.2011 14 11.10.2011 14 23.01.2012 14 19.04.2012 14 22.10.2012 14 15.01.2013 14 06.05.2013 18 23.11.2012 18 05.06.2013 18 19.08.2013 18 11.04.2014 18 18.07.2014
需求是仅保留每个ID每年对应的Date记录数≤3的行,预期结果如下:
ID Date 14 25.02.2010 14 08.07.2010 14 20.10.2010 14 07.01.2011 14 20.04.2011 14 02.07.2011 14 11.10.2011 14 23.01.2012 14 19.04.2012 14 22.10.2012
之前用groupby+size得到的是分组汇总结果,无法直接用来筛选原数据,需要调整方法。
解决方案
核心思路是:用transform方法将分组统计的记录数映射到原DataFrame的每一行,再基于这个值筛选符合条件的行。
方法1:简洁写法(一步到位)
# 直接按ID和年份分组,用transform获取每行对应的组记录数,再筛选 result = df[df.groupby(['ID', df['Date'].dt.year])['Date'].transform('size') <= 3]
方法2:分步拆解(更易理解)
如果想清晰查看中间步骤,可以拆分执行:
# 1. 从Date列提取年份,生成辅助列 df['year'] = df['Date'].dt.year # 2. 按ID和year分组,计算每组的记录数,并映射到每行 df['record_count'] = df.groupby(['ID', 'year'])['Date'].transform('size') # 3. 筛选记录数≤3的行,最后移除辅助列 result = df[df['record_count'] <= 3].drop(columns=['year', 'record_count'])
原理说明
groupby(['ID', df['Date'].dt.year]):按ID和年份分组,确保统计的是每个ID在每一年的记录数transform('size'):将分组后的统计结果(每组的记录数)广播到该组的每一行,让原DataFrame的每一行都能拿到自己所在组的记录数- 最后通过布尔索引筛选出记录数≤3的行,即可得到符合需求的结果
内容的提问来源于stack exchange,提问作者Konstantin Moser
相关产品推荐
相关产品推荐

