如何按ID分组与年月,保留每组每月最后重复行仅一行
解决方案
步骤1:转换日期格式并提取年月
先把字符串类型的Date列转为datetime格式,同时提取年月字段作为分组依据:
import pandas as pd # 构造示例数据 data = [ ["AAA", "2021-06-05", 14, "A"], ["AAA", "2021-06-12", 11, "B"], ["AAA", "2021-06-12", 11, "C"], ["AAA", "2021-06-12", 11, "D"], ["AAA", "2021-06-21", 15, "E"], ["AAA", "2021-06-22", 15, "F"], ["AAA", "2021-06-22", 15, "G"], ["BBB", "2021-06-06", 33, "H"], ["BBB", "2021-06-18", 35, "I"], ["BBB", "2021-06-27", 55, "J"], ["BBB", "2021-06-27", 55, "K"], ["BBB", "2021-06-27", 55, "L"], ["BBB", "2021-06-27", 55, "M"], ["AAA", "2021-07-08", 6, "N"], ["AAA", "2021-07-08", 6, "O"], ["AAA", "2021-07-12", 8, "P"], ["AAA", "2021-07-12", 8, "Q"], ] df = pd.DataFrame(data, columns=["ID", "Date", "Day_Val", "Title"]) # 转换Date列为datetime类型 df["Date"] = pd.to_datetime(df["Date"]) # 提取年月,用于分组 df["Year_Month"] = df["Date"].dt.to_period("M")
步骤2:标记并筛选目标行
给每行添加两个标识,再根据需求筛选出需要保留的行:
# 按ID和Year_Month分组,计算每个分组的最晚日期 max_date_per_group = df.groupby(["ID", "Year_Month"])["Date"].transform("max") df["Is_Latest_Date"] = df["Date"] == max_date_per_group # 按ID和Date分组,标记每行是否是该日期组的最后一行 df["Is_Last_Row_In_Date"] = df.groupby(["ID", "Date"]).cumcount(ascending=False) == 0 # 筛选条件:要么不是最晚日期的行,要么是最晚日期组里的最后一行 filtered_df = df[(~df["Is_Latest_Date"]) | (df["Is_Last_Row_In_Date"])] # 移除辅助列,恢复原列顺序 filtered_df = filtered_df.drop(["Year_Month", "Is_Latest_Date", "Is_Last_Row_In_Date"], axis=1).reset_index(drop=True)
验证结果
执行以下代码即可得到目标输出:
print(filtered_df)
输出结果:
ID Date Day_Val Title 0 AAA 2021-06-05 14 A 1 AAA 2021-06-12 11 B 2 AAA 2021-06-12 11 C 3 AAA 2021-06-12 11 D 4 AAA 2021-06-21 15 E 5 AAA 2021-06-22 15 G 6 BBB 2021-06-06 33 H 7 BBB 2021-06-18 35 I 8 BBB 2021-06-27 55 M 9 AAA 2021-07-08 6 N 10 AAA 2021-07-08 6 O 11 AAA 2021-07-12 8 Q
逻辑说明
- 日期转换与年月提取:将字符串日期转为datetime后,提取年月作为分组维度,确保我们能按
ID+年月的范围处理数据。 - 标记最晚日期:通过分组取最大值,识别出每个
ID+年月分组里的最晚日期行。 - 标记日期组最后一行:用倒序计数的方式,定位每个
ID+日期组里的最后一行。 - 筛选逻辑:保留所有非最晚日期的行,同时仅保留最晚日期组里的最后一行,完全匹配需求。
内容的提问来源于stack exchange,提问作者ImNotSureAboutStats
相关产品推荐
相关产品推荐

