在两个含时间列的DataFrame中查找满足非负时间差的最近行
解决思路与实现方案
刚好碰到过类似的需求,用pandas的话有两种高效的方法,因为你的两个DataFrame已经是时间戳唯一且已排序的,这就省去了很多预处理步骤,直接可以用专门的工具来做:
方法一:用merge_asof(推荐,简洁高效)
merge_asof是pandas专门为按最近键合并排序数据集设计的函数,完美匹配你的场景——我们只需要指定direction='forward',就能找到每个短时间点之后或同时的最近长时间点。
代码示例
import pandas as pd # 替换成你实际的DataFrame mytime_short = pd.DataFrame( {'mytime_short': pd.to_datetime(['2023-01-01 10:00', '2023-01-01 10:15', '2023-01-01 10:30'])} ) # 先把mytime_long的原index保留下来,因为你需要输出这个字段 mytime_long = pd.DataFrame( {'mytime_long': pd.to_datetime(['2023-01-01 09:50', '2023-01-01 10:10', '2023-01-01 10:20', '2023-01-01 10:40'])} ).reset_index() # 新增index列,对应原DataFrame的索引 # 执行合并,forward方向表示找>=左表时间的最近右表记录 result = pd.merge_asof( mytime_short, mytime_long, left_on='mytime_short', right_on='mytime_long', direction='forward' ) # 整理成你需要的输出结构 result = result[['mytime_short', 'index', 'mytime_long']] print(result)
输出效果
mytime_short index mytime_long 0 2023-01-01 10:00:00 1 2023-01-01 10:10:00 1 2023-01-01 10:15:00 2 2023-01-01 10:20:00 2 2023-01-01 10:30:00 3 2023-01-01 10:40:00
如果某个mytime_short的时间晚于mytime_long的所有时间,对应的index和mytime_long会自动设为NaN,方便你后续处理。
方法二:用numpy.searchsorted(更灵活,适合自定义逻辑)
如果需要更精细的控制,可以用numpy的searchsorted函数——它能快速找到每个短时间点在已排序的长时间序列中的插入位置,这个位置就是第一个>=该时间点的记录索引。
代码示例
import pandas as pd import numpy as np # 替换成你实际的DataFrame mytime_short = pd.DataFrame( {'mytime_short': pd.to_datetime(['2023-01-01 10:00', '2023-01-01 10:15', '2023-01-01 10:30'])} ) mytime_long = pd.DataFrame( {'mytime_long': pd.to_datetime(['2023-01-01 09:50', '2023-01-01 10:10', '2023-01-01 10:20', '2023-01-01 10:40'])} ) # 获取已排序的长时间数组 long_time_values = mytime_long['mytime_long'].values # 找到每个短时间点对应的插入位置(即第一个>=它的长时间索引) match_indices = np.searchsorted(long_time_values, mytime_short['mytime_short'].values, side='left') # 构建结果DataFrame,处理边界情况(比如短时间晚于所有长时间,设为NaN) result = mytime_short.copy() result['index'] = np.where(match_indices < len(long_time_values), match_indices, np.nan) # 匹配对应的长时间戳 result['mytime_long'] = mytime_long.loc[match_indices[match_indices < len(long_time_values)], 'mytime_long'] \ .reindex(result.index).values print(result)
注意事项
- 确保两个DataFrame的时间列都是pandas datetime类型,如果不是,可以用
pd.to_datetime()转换; - 因为题目说每个DataFrame内的时间戳唯一,所以不用处理重复时间的冲突问题;
- 如果需要丢弃没有匹配结果(即时间晚于所有长时间)的行,可以用
result.dropna(subset=['index'])。
内容的提问来源于stack exchange,提问作者00__00__00
相关产品推荐
相关产品推荐

