如何用Pandas按ID关联时间区间合并数据并处理缺失区间?
解决Pandas中按ID匹配日期区间的问题
嘿,我来帮你搞定这个Pandas的日期区间匹配问题!你之前遇到的KeyError是因为用IntervalIndex做索引时,df1里的很多日期不在任何区间里,而且原方法没考虑同一个ID对应多个区间的情况,咱们换个思路来解决。
核心思路
先按ID把两个DataFrame合并,让每个df1的日期都能对应到该ID的所有区间,然后检查日期是否落在任一区间内,最后按ID和日期聚合结果。
完整解决方案
步骤1:准备数据并确保日期类型正确
首先要把所有日期列转换成datetime类型,这是后续比较的基础:
import pandas as pd from io import StringIO # 构造df1 data_df1 = """ ID,Date 1,2022-02-01 1,2022-02-02 1,2022-02-03 1,2022-02-04 1,2022-02-05 1,2022-02-06 1,2022-02-07 2,2022-02-01 2,2022-02-02 2,2022-02-03 2,2022-02-04 2,2022-02-05 2,2022-02-06 2,2022-02-07 2,2022-02-08 """ df1 = pd.read_csv(StringIO(data_df1), parse_dates=['Date']) # 构造包含多区间的df2 data_df2 = """ ID;Start;End 1;2022-02-02;2022-02-04 1;2022-02-06;2022-02-07 2;2022-02-04;2022-02-06 """ df2 = pd.read_csv(StringIO(data_df2), sep=';', parse_dates=['Start', 'End'])
步骤2:按ID合并两个DataFrame
用merge按ID做左连接,这样df1的每一行都会和对应ID的所有区间匹配:
merged = df1.merge(df2, on='ID', how='left')
步骤3:判断日期是否在区间内
用向量运算(比逐行apply效率更高)判断每个日期是否落在对应区间里,同时处理没有区间的情况(填充False):
# 日期在[Start, End]区间内的判断 merged['in_interval'] = (merged['Date'] >= merged['Start']) & (merged['Date'] <= merged['End']) # 对没有匹配到区间的行(Start/End为NaN)填充False merged['in_interval'] = merged['in_interval'].fillna(False)
步骤4:聚合结果
按ID和Date分组,只要该日期属于该ID的任一区间,就标记为True:
result = merged.groupby(['ID', 'Date'])['in_interval'].any().reset_index()
最终结果
运行后得到的result如下:
ID Date in_interval 0 1 2022-02-01 False 1 1 2022-02-02 True 2 1 2022-02-03 True 3 1 2022-02-04 True 4 1 2022-02-05 False 5 1 2022-02-06 True 6 1 2022-02-07 True 7 2 2022-02-01 False 8 2 2022-02-02 False 9 2 2022-02-03 False 10 2 2022-02-04 True 11 2 2022-02-05 True 12 2 2022-02-06 True 13 2 2022-02-07 False 14 2 2022-02-08 False
为什么之前的方法失效?
你之前用IntervalIndex的方法有两个问题:
- 未关联ID:直接用日期作为索引查找区间,会把不同ID的区间混在一起,逻辑错误。
- KeyError:df1中不在任何区间的日期无法在索引中找到,触发报错。
而这个新方法完美解决了这两个问题,还支持单个ID对应多个区间的场景,效率也更高。
内容的提问来源于stack exchange,提问作者John Smith
相关产品推荐
相关产品推荐

