You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas如何删除被更大时间区间完全覆盖的区间记录

解决方案

overlaps() 方法仅能判断两个区间是否存在交集,无法区分「当前区间覆盖其他区间」和「当前区间被其他区间覆盖」两种场景,直接基于重叠结果过滤会误删覆盖范围最大的区间。我们可以通过区间端点的大小比较,直接判断区间是否被完全覆盖。

基础实现(适合小数据集)

核心判断规则:一个区间需要被删除,当且仅当存在另一个不同的区间,其开始时间早于等于当前区间开始时间,且结束时间晚于等于当前区间结束时间。

import pandas as pd
import numpy as np

# 构造示例DataFrame
arrays = [
    [pd.Timestamp(2022,1,1), pd.Timestamp(2022,2,1), pd.Timestamp(2022,1,1), pd.Timestamp(2022,4,1)],
    [pd.Timestamp(2022,1,31), pd.Timestamp(2022,2,28), pd.Timestamp(2022,3,30), pd.Timestamp(2022,4,30)]
]
idx = pd.MultiIndex.from_arrays(arrays)
df = pd.DataFrame(np.zeros(4), index=idx)

# 提取全量区间的起止时间
all_start = df.index.get_level_values(0).values
all_end = df.index.get_level_values(1).values

# 逐行判断是否被其他区间覆盖
covered_flag = []
for i in range(len(df)):
    s, e = all_start[i], all_end[i]
    # 统计满足「起点<=当前起点、终点>=当前终点」的区间数量,排除自身后数量>0则说明被覆盖
    cover_count = ((all_start <= s) & (all_end >= e)).sum()
    covered_flag.append(cover_count > 1)

# 过滤被覆盖的行
res = df[~np.array(covered_flag)]

运行后输出结果符合预期:

0
2022-01-01 2022-03-30  0.0
2022-04-01 2022-04-30  0.0

性能优化版本(适合十万级以上大数据集)

基础实现的时间复杂度为O(n²),数据量大时运行效率低,可以通过排序后单次遍历将复杂度降到O(nlogn):

  1. 先对所有区间按开始时间升序、结束时间降序排序
  2. 维护遍历过程中遇到的最大结束时间,排序后当前区间的开始时间一定大于等于之前所有区间的开始时间,只要当前区间结束时间小于等于历史最大结束时间,就说明当前区间被之前的某个区间完全覆盖
# 按索引排序:第一层开始时间升序,第二层结束时间降序
sorted_df = df.sort_index(ascending=[True, False])
sorted_end = sorted_df.index.get_level_values(1).values

keep_mask = []
current_max_end = None
for e in sorted_end:
    if current_max_end is None or e > current_max_end:
        keep_mask.append(True)
        current_max_end = e
    else:
        keep_mask.append(False)

res = sorted_df[keep_mask]

注:新版Pandas中已弃用pd.datetime,统一使用pd.Timestamp生成时间对象。

内容的提问来源于stack exchange,提问作者W. Walter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 01:42:17