如何在Pandas中按ID分组剔除7天内的观测值(保留最早日期)
问题描述
现有包含ID和Date列的Pandas DataFrame,数据如下:
| ID | Date |
|---|---|
| 111 | 16/09/2021 |
| 111 | 14/03/2022 |
| 111 | 18/03/2022 |
| 111 | 21/03/2022 |
| 111 | 22/03/2022 |
| 222 | 27/03/2022 |
| 222 | 30/03/2022 |
| 222 | 4/04/2022 |
| 222 | 6/04/2022 |
| 222 | 13/04/2022 |
需要按ID分组筛选数据:剔除彼此间隔7天内的观测值,保留每组对应区间的最早日期,最终使每个ID的日期间隔均超过7天,期望结果如下:
| ID | Date |
|---|---|
| 111 | 16/09/2021 |
| 111 | 14/03/2022 |
| 111 | 22/03/2022 |
| 222 | 27/03/2022 |
| 222 | 4/04/2022 |
| 222 | 13/04/2022 |
Pandas实现方案
针对需求,分步骤实现如下:
1. 准备环境与数据
首先导入Pandas库,并构造示例数据(如果你的数据来自文件,可替换为pd.read_csv等读取方式):
import pandas as pd # 构造示例数据 data = { 'ID': [111, 111, 111, 111, 111, 222, 222, 222, 222, 222], 'Date': ['16/09/2021', '14/03/2022', '18/03/2022', '21/03/2022', '22/03/2022', '27/03/2022', '30/03/2022', '4/04/2022', '6/04/2022', '13/04/2022'] } df = pd.DataFrame(data)
2. 转换日期格式
原始Date列是字符串,无法直接计算日期间隔,需转换为Pandas的datetime类型:
# 指定格式为日/月/年,确保转换正确 df['Date'] = pd.to_datetime(df['Date'], format='%d/%m/%Y')
3. 定义分组筛选函数
编写函数处理每个ID分组:按日期排序后,依次判断每个日期与最后一个保留日期的间隔,仅保留间隔超过7天的日期(保留区间最早值):
def filter_dates(group): # 先按日期排序,确保顺序正确(即使原数据有序,这一步也能避免异常) group_sorted = group.sort_values('Date').reset_index(drop=True) # 初始化保留列表,先加入第一个日期 kept_dates = [group_sorted.iloc[0]['Date']] # 遍历后续所有日期 for idx in range(1, len(group_sorted)): current_date = group_sorted.iloc[idx]['Date'] # 计算当前日期与最后一个保留日期的天数差 days_diff = (current_date - kept_dates[-1]).days # 间隔超过7天则保留 if days_diff > 7: kept_dates.append(current_date) # 返回筛选后的分组数据 return group_sorted[group_sorted['Date'].isin(kept_dates)]
4. 分组应用筛选函数
按ID分组后,应用上述函数完成筛选:
# group_keys=False避免结果中保留分组键的层级索引 result_df = df.groupby('ID', group_keys=False).apply(filter_dates) # 可选:将日期转回原字符串格式(如果需要展示为日/月/年) result_df['Date'] = result_df['Date'].dt.strftime('%d/%m/%Y') # 查看结果 print(result_df)
执行后即可得到符合期望的筛选结果。
内容的提问来源于stack exchange,提问作者winlai
相关产品推荐
相关产品推荐

