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

pandas无apply高效判断多个时间戳是否落在每行START和END区间内

Pandas无apply实现判断时间区间是否包含指定时间点

原方案错误原因

原写法分开判断「存在时间戳≥当前行START」和「存在时间戳≤当前行END」,没有要求两个条件对应同一个时间戳,因此当出现比如["2019-01-01", "2021-01-01"]这类跨全区间的时间戳组合时,会输出全True的错误结果。

高性能实现方案

方案1:numpy广播向量化实现(逻辑直观,通用场景首选)

利用numpy广播机制直接生成二维布尔矩阵判断,全程无Python级循环,性能远高于apply:

import numpy as np
import pandas as pd

# 你的原始数据和timestamps定义部分
data = [["2020-01-01", "2020-01-01"], ["2020-01-02", "2020-01-04"], ["2020-01-05", "2020-01-06"]]
df = pd.DataFrame(data, columns=["START", "END"]).astype({"END": "datetime64[ns]" , "START": "datetime64[ns]"})
timestamps = pd.Series(["2020-01-02", "2020-01-03"], dtype="datetime64[ns]")

# 核心逻辑
# 构造 (df行数, timestamps长度) 的布尔矩阵,逐元素判断时间戳是否≥对应行START
mask_ge_start = df["START"].values[:, np.newaxis] <= timestamps.values
# 构造同维度布尔矩阵,逐元素判断时间戳是否≤对应行END
mask_le_end = df["END"].values[:, np.newaxis] >= timestamps.values
# 逐行检查是否至少有一个时间戳同时满足两个条件
df["has_match"] = (mask_ge_start & mask_le_end).any(axis=1)

输出的has_match列结果为[False, True, False],符合预期;如果用错误测试用的timestamps["2019-01-01", "2021-01-01"],输出结果为全False,完全正确。

方案2:IntervalIndex实现(适合timestamps数量远小于df行数的场景)

如果timestamps的长度远小于df的行数,可以用IntervalIndex进一步优化性能:

# 构造左闭右闭的区间索引
intervals = pd.IntervalIndex.from_arrays(df["START"], df["END"], closed="both")
# 查找每个时间戳命中的区间位置
hit_indexes = intervals.get_indexer(timestamps)
# 标记有命中的行
df["has_match"] = df.index.isin(hit_indexes[hit_indexes != -1])

该方案时间复杂度仅为O(n + m log n)(n为df行数,m为timestamps长度),在df行数很大、timestamps很少的场景下性能优势更明显。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 03:36:03