如何使用Python Pandas高效筛选与指定日期范围存在重叠的行?
我有一个包含start和end日期列的DataFrame,初始化代码如下:
import pandas as pd import datetime data=[["2016-10-17","2017-03-08"],["2014-08-17","2016-09-08"],["2014-01-01","2015-01-01"],["2017-12-20","2019-01-01"]] df=pd.DataFrame(data,columns=['start','end']) df['start'] = pd.to_datetime(df['start'], format='%Y-%m-%d') df['end'] = pd.to_datetime(df['end'], format='%Y-%m-%d')
初始化后的DataFrame:
start end
0 2016-10-17 2017-03-08
1 2014-08-17 2016-09-08
2 2014-01-01 2015-01-01
3 2017-12-20 2019-01-01
我设置了参考日期范围:
ref_start=datetime.date(2015, 9, 20) ref_end=datetime.date(2017,1,31) print(ref_start,ref_end)
输出:2015-09-20 2017-01-31
我需要筛选出DataFrame中日期范围(start到end)与参考范围存在重叠的行,预期结果是:
start end
0 2016-10-17 2017-03-08
1 2014-08-17 2016-09-08
我尝试了这段代码但无法正常运行:
df[(max(df['start'],ref_start)>min(df['end'],ref_end))]
请问有没有高效实现预期结果的方法?
首先,你之前的代码出错是因为max(df['start'], ref_start)这种写法逻辑不对——max函数无法直接对pandas的Series和单个日期值做元素级的比较,它会尝试把整个Series当作一个整体和单个值对比,自然会出错。
要判断两个日期范围是否重叠,核心逻辑很清晰:两个范围存在重叠的条件是,当前行的start小于参考范围的end,并且当前行的end大于参考范围的start。反过来想,如果当前行的end <= 参考start,或者当前行的start >= 参考end,那这两个范围就完全不重叠,我们只需要排除这些情况即可。
用pandas的向量化操作可以高效实现这个逻辑,代码如下:
# 先把参考日期转成datetime类型,和DataFrame的列类型统一,避免类型不匹配问题 ref_start_dt = pd.to_datetime(ref_start) ref_end_dt = pd.to_datetime(ref_end) # 构建筛选掩码:当前范围与参考范围存在重叠 mask = (df['start'] < ref_end_dt) & (df['end'] > ref_start_dt) filtered_df = df[mask]
运行这段代码后,filtered_df就是你想要的结果:
start end
0 2016-10-17 2017-03-08
1 2014-08-17 2016-09-08
为什么这个方法高效?
pandas的向量化操作基于numpy实现,会对整个Series进行批量运算,比循环遍历每一行的速度快得多,尤其是当你的DataFrame数据量很大时,这种方法的性能优势会非常明显。同时,统一日期类型也能避免隐性的类型转换错误,让运算更稳定。
内容的提问来源于stack exchange,提问作者user14742805

