Pandas:删除日期时间区间冲突记录,保留最新日志时间行
Pandas 按日志时间保留无重叠时间区间记录实现
需求说明
现有包含3个datetime类型列的pandas DataFrame:
log time:日志生成时间start:时间区间起始点end:时间区间结束点
处理规则:当多条记录的[start, end]时间区间存在重叠冲突时,仅保留log time最新的记录,删除其余冲突记录。
示例原始数据
| name | start | end | log time |
|---|---|---|---|
| r1 | 2022/08/05 09:00:00 | 2022/08/07 08:00:00 | 2022/08/06 08:00:00 |
| r2 | 2022/08/06 09:00:00 | 2022/08/08 08:00:00 | 2022/08/05 08:00:00 |
| r3 | 2022/08/07 09:00:00 | 2022/08/09 08:00:00 | 2022/08/04 08:00:00 |
示例中r1和r2的时间区间重叠,r1的log time更新,因此保留r1删除r2;r3和其他记录无区间重叠直接保留。
期望输出结果
| name | start | end | log time |
|---|---|---|---|
| r1 | 2022/08/05 09:00:00 | 2022/08/07 08:00:00 | 2022/08/06 08:00:00 |
| r3 | 2022/08/07 09:00:00 | 2022/08/09 08:00:00 | 2022/08/04 08:00:00 |
实现代码
核心逻辑:
- 先按
log time降序排序,保证最新的记录排在最前,遍历的时候优先处理优先级最高(最新)的记录 - 维护已保留的无冲突区间列表,逐行判断当前记录和所有已保留区间是否重叠,无重叠则保留,否则丢弃
- 区间重叠判定规则:两个区间
[s1,e1]和[s2,e2],只要不满足e1 <= s2(当前区间在已保留区间之前)或e2 <= s1(当前区间在已保留区间之后),就判定为重叠
import pandas as pd # 构造示例测试数据 df = pd.DataFrame({ 'name': ['r1', 'r2', 'r3'], 'start': pd.to_datetime([ '2022/08/05 09:00:00', '2022/08/06 09:00:00', '2022/08/07 09:00:00' ]), 'end': pd.to_datetime([ '2022/08/07 08:00:00', '2022/08/08 08:00:00', '2022/08/09 08:00:00' ]), 'log time': pd.to_datetime([ '2022/08/06 08:00:00', '2022/08/05 08:00:00', '2022/08/04 08:00:00' ]) }) # 按日志时间降序排序,最新记录优先 df_sorted = df.sort_values(by='log time', ascending=False).reset_index(drop=True) keep_rows = [] kept_intervals = [] for _, row in df_sorted.iterrows(): cur_s, cur_e = row['start'], row['end'] has_overlap = False # 遍历所有已保留区间检查重叠 for kept_s, kept_e in kept_intervals: if not (cur_e <= kept_s or cur_s >= kept_e): has_overlap = True break if not has_overlap: keep_rows.append(row) kept_intervals.append((cur_s, cur_e)) # 组装结果,可按需调整结果排序规则 result = pd.DataFrame(keep_rows).reset_index(drop=True)
补充说明
- 上述代码对边界值做了兼容:如果前一个区间的
end等于后一个区间的start(比如示例中r1的end是2022/08/07 08:00:00,r3的start是2022/08/07 09:00:00),判定为不重叠,符合常规时间区间左闭右开的约定 - 如果数据量超过10万条,可以把已保留的区间按
start排序后用二分查找优化重叠判断的效率,常规数据量下上述遍历逻辑性能足够 - 代码中所有时间列会自动保留datetime类型,无需额外转换
内容的提问来源于stack exchange,提问作者mert
相关产品推荐
相关产品推荐

