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

如何高效删除pandas DataFrame中多个指定时间范围对应的行

高效删除Pandas DataFrame中多个时间区间行的方案

你原有方案慢的核心原因是:每次循环都会触发全表索引查找、行删除、新DataFrame生成,多次内存拷贝的开销随着数据量和区间数量增长会被急剧放大。以下是几种效率远高于循环删除的实现方案:

前置准备

首先确保你的时间列(或时间索引)已经转换为datetime类型,若使用时间作为索引建议提前排序,可以大幅提升区间查找效率:

# 若时间是索引
df.index = pd.to_datetime(df.index)
df = df.sort_index()

# 若时间是普通列,列名为ts
df['ts'] = pd.to_datetime(df['ts'])

方案1:布尔掩码单次过滤(通用场景首选)

一次性标记所有需要删除的行,最后只做一次数据过滤,仅触发一次内存拷贝:

# 先把待删除区间转换为datetime类型
drop_intervals = [(pd.to_datetime(start), pd.to_datetime(end)) for start, end in drop_pairs]

# 初始化全为False的掩码
drop_mask = pd.Series(False, index=df.index)

# 遍历区间标记要删除的行
for start, end in drop_intervals:
    # 时间作为索引的写法
    drop_mask |= (df.index >= start) & (df.index <= end)
    # 若时间是普通列,替换为:
    # drop_mask |= (df['ts'] >= start) & (df['ts'] <= end)

# 单次过滤保留不需要删除的行
df = df[~drop_mask]

方案2:IntervalIndex批量判断(区间数量多的场景首选)

如果待删除的区间数量很大,可以用Pandas内置的IntervalIndex做向量化判断,避免Python层循环:

# 转换区间为IntervalArray
drop_intervals = pd.arrays.IntervalArray.from_tuples(
    [(pd.to_datetime(s), pd.to_datetime(e)) for s,e in drop_pairs],
    closed='both' # 闭区间,匹配你原有写法的包含起止时间的逻辑
)

# 向量化判断每个行的时间是否落在任意待删除区间内
# 时间作为索引的写法
drop_mask = drop_intervals.get_indexer(df.index) != -1
# 若时间是普通列,替换为:
# drop_mask = drop_intervals.get_indexer(df['ts']) != -1

df = df[~drop_mask]

方案3:searchsorted二分查找(超大表+有序时间索引场景首选)

如果你的表已经用排序后的Datetime作为索引,可以用二分查找定位每个区间的起止位置,时间复杂度是O(log n) per区间,超大数据量下性能最优:

drop_intervals = [(pd.to_datetime(start), pd.to_datetime(end)) for start, end in drop_pairs]
drop_indices = []

for start, end in drop_intervals:
    # 二分查找区间左右边界的位置
    left_pos = df.index.searchsorted(start)
    right_pos = df.index.searchsorted(end, side='right')
    # 收集待删除的索引
    drop_indices.extend(df.index[left_pos:right_pos])

# 一次性删除所有待删行
df = df.drop(drop_indices)

内容的提问来源于stack exchange,提问作者tiddlz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 01:45:03