Python中高效匹配两个DataFrame日期区间并赋值价格字段
高效解决DataFrame区间匹配问题
问题回顾
你有两个DataFrame:
- df1包含月份及对应的起止日期:
Month Month_Start Month_End Month1 2022-03-27 2022-04-30 Month2 2022-05-01 2022-05-28 Month3 2022-05-01 2022-06-25
- df2包含价格区间及对应价格:
start_Month end_Month price 2022-03-27 2260-12-31 1 2022-03-27 2260-12-31 2 2022-03-27 2260-12-31 3
需要匹配df1的[Month_Start, Month_End]完全处于df2的[start_Month, end_Month]区间内的记录,将price关联到对应Month行,最终得到每个Month对应一个price的结果。
原嵌套for循环在数据量1000+时性能极差,以下是两种高效解决方案:
方案一:笛卡尔积+矢量化过滤(通用高效)
利用pandas的merge做笛卡尔积,再通过矢量化条件过滤,最后按需求聚合结果,全程避免Python级别的循环:
import pandas as pd # 1. 先将所有日期列转为datetime类型(必须,否则字符串比较可能出错) df1['Month_Start'] = pd.to_datetime(df1['Month_Start']) df1['Month_End'] = pd.to_datetime(df1['Month_End']) df2['start_Month'] = pd.to_datetime(df2['start_Month']) df2['end_Month'] = pd.to_datetime(df2['end_Month']) # 2. 添加临时键实现笛卡尔积合并 df1['tmp_key'] = 1 df2['tmp_key'] = 1 merged = pd.merge(df1, df2, on='tmp_key').drop('tmp_key', axis=1) # 3. 过滤符合区间包含条件的行 filtered = merged[(merged['Month_Start'] >= merged['start_Month']) & (merged['Month_End'] <= merged['end_Month'])] # 4. 按Month分组取目标price(这里取第一个匹配的price,可根据需求改为min/max等) result = filtered.groupby('Month')['price'].first().reset_index() print(result)
输出结果:
Month price 0 Month1 1 1 Month2 1 2 Month3 1
方案二:IntervalIndex匹配(更简洁高效)
利用pandas的IntervalIndex类型,直接判断区间包含关系,适合区间匹配场景:
import pandas as pd # 1. 转换日期列为datetime类型 df1['Month_Start'] = pd.to_datetime(df1['Month_Start']) df1['Month_End'] = pd.to_datetime(df1['Month_End']) df2['start_Month'] = pd.to_datetime(df2['start_Month']) df2['end_Month'] = pd.to_datetime(df2['end_Month']) # 2. 给df2创建区间索引 df2_intervals = pd.IntervalIndex.from_arrays(df2['start_Month'], df2['end_Month'], closed='both') # 3. 给df1创建区间数组,判断每个区间是否被df2的任意区间包含 df1_intervals = pd.IntervalIndex.from_arrays(df1['Month_Start'], df1['Month_End'], closed='both') # 找出所有df1区间对应的匹配df2行(这里取第一个匹配的price) matched_price = df2.loc[df1_intervals.isin(df2_intervals).any(axis=0), 'price'].iloc[0] # 4. 生成结果 result = df1[['Month']].assign(price=matched_price) print(result)
性能说明
原嵌套for循环是Python级别的逐行遍历,时间复杂度为O(n*m);而上述两种方案基于pandas的C底层矢量化操作,时间复杂度大幅降低,处理1000+行数据时速度提升可达几十甚至上百倍。
内容的提问来源于stack exchange,提问作者ThunderCloud
相关产品推荐
相关产品推荐

