如何基于日期范围合并两个Pandas DataFrame?
基于时间范围匹配合并Pandas DataFrame
方案一:交叉合并+范围筛选
先通过交叉合并生成所有可能的时间匹配组合,再筛选出符合4小时K线时间范围的记录,最后合并回原df2得到结果:
import pandas as pd df1 = pd.DataFrame({ 'a': ['2024-01-01 04:00:00', '2023-02-02 20:00:00'], 'id': ['a_1', 'a_2']}) df1['a'] = pd.to_datetime(df1.a) # 计算4小时K线的结束时间(起始时间+3小时) df1['b'] = df1['a'] + pd.Timedelta(hours=3) df2 = pd.DataFrame({ 'a': [ '2024-01-01 4:00:00', '2024-01-01 05:00:00', '2024-01-01 06:00:00', '2024-01-01 07:00:00', '2024-01-01 08:00:00', '2024-01-01 09:00:00', '2023-02-02 21:00:00', '2023-02-02 23:00:00']}) df2['a'] = pd.to_datetime(df2.a) # 交叉合并df2和df1,生成所有可能的组合 merged = df2.merge(df1, how='cross', suffixes=('_df2', '_df1')) # 筛选df2时间落在df1的[起始时间, 起始时间+3h]范围内的记录 filtered = merged[(merged['a_df2'] >= merged['a_df1']) & (merged['a_df2'] <= merged['b'])] # 合并回df2,未匹配的记录自动填充NaN result = df2.merge(filtered[['a_df2', 'id']], left_on='a', right_on='a_df2', how='left').drop('a_df2', axis=1) print(result)
方案二:使用merge_asof高效匹配(适合大数据集)
merge_asof是Pandas专为时间序列匹配设计的函数,效率远高于交叉合并,需先对两个DataFrame按时间排序:
import pandas as pd df1 = pd.DataFrame({ 'a': ['2024-01-01 04:00:00', '2023-02-02 20:00:00'], 'id': ['a_1', 'a_2']}) df1['a'] = pd.to_datetime(df1.a) df1['b'] = df1['a'] + pd.Timedelta(hours=3) df2 = pd.DataFrame({ 'a': [ '2024-01-01 4:00:00', '2024-01-01 05:00:00', '2024-01-01 06:00:00', '2024-01-01 07:00:00', '2024-01-01 08:00:00', '2024-01-01 09:00:00', '2023-02-02 21:00:00', '2023-02-02 23:00:00']}) df2['a'] = pd.to_datetime(df2.a) # 按时间列排序(merge_asof要求的前提条件) df1_sorted = df1.sort_values('a') df2_sorted = df2.sort_values('a') # 执行时间范围匹配:允许精确匹配,设置3小时的时间容忍度 result = pd.merge_asof( df2_sorted, df1_sorted, left_on='a', right_on='a', direction='backward', allow_exact_matches=True, tolerance=pd.Timedelta(hours=3) ).drop('b', axis=1) # 恢复原df2的行顺序 result = result.set_index('a').reindex(df2['a']).reset_index() print(result)
两种方案均可输出目标结果:
a id 0 2024-01-01 04:00:00 a_1 1 2024-01-01 05:00:00 a_1 2 2024-01-01 06:00:00 a_1 3 2024-01-01 07:00:00 a_1 4 2024-01-01 08:00:00 NaN 5 2024-01-01 09:00:00 NaN 6 2023-02-02 21:00:00 a_2 7 2023-02-02 23:00:00 a_2
内容的提问来源于stack exchange,提问作者AmirX
相关产品推荐
相关产品推荐

