如何基于Pandas从价格DataFrame匹配条件为订单DataFrame新增市场价格时间列
如何基于Pandas从价格DataFrame匹配条件为订单DataFrame新增市场价格时间列
嘿,我来帮你搞定这个需求!你的目标是给orders数据框新增一列marketPriceTime,要找到prices里价格等于订单价格、且时间不晚于订单时间的最后一条记录的时间,没有匹配项就返回None对吧?
先把你的示例数据贴出来,方便大家理解场景:
import pandas as pd prices = pd.DataFrame({'time': range(10), 'price': [20, 21, 22, 21, 22, 23, 24, 25, 26, 27]}) orders = pd.DataFrame({'time': [3, 6, 8], 'orderPrice' : [20, 24, 18]})
方法一:简单直接的Apply实现
适合数据量不大的场景,逻辑清晰易懂:
我们可以写一个小函数,对orders的每一行做筛选和取值,然后用apply批量处理:
def get_last_valid_market_time(row, prices_df): # 筛选符合条件的价格记录:价格匹配 + 时间≤订单时间 matched_rows = prices_df[(prices_df['price'] == row['orderPrice']) & (prices_df['time'] <= row['time'])] # 有匹配结果就取最大的时间(即最后出现的那条),没有就返回None return matched_rows['time'].max() if not matched_rows.empty else None # 给orders新增目标列 orders['marketPriceTime'] = orders.apply(lambda x: get_last_valid_market_time(x, prices), axis=1)
运行后你会得到想要的结果:
time orderPrice marketPriceTime 0 3 20 0.0 1 6 24 6.0 2 8 18 NaN
(注:Pandas里默认用NaN表示空值,和你示例里的None是等价的,如果需要强制显示None,可以用orders['marketPriceTime'] = orders['marketPriceTime'].where(pd.notnull(orders['marketPriceTime']), None)转换一下)
方法二:高效优化版(适合大数据集)
如果你的prices或orders数据量很大,上面的apply会因为逐行遍历效率偏低。我们可以先分组预处理prices,再用二分查找快速匹配:
# 先按价格分组,把每个价格对应的时间列表排序好,存成字典 price_time_map = prices.groupby('price')['time'].apply(sorted).to_dict() def fast_match_market_time(row, price_time_dict): # 获取当前订单价格对应的时间列表 time_list = price_time_dict.get(row['orderPrice'], []) if not time_list: return None # 用二分查找找到最大的≤订单时间的索引 import bisect idx = bisect.bisect_right(time_list, row['time']) - 1 # 索引有效就返回对应时间,否则返回None return time_list[idx] if idx >= 0 else None # 批量处理订单 orders['marketPriceTime'] = orders.apply(lambda x: fast_match_market_time(x, price_time_map), axis=1)
这个方法的优势在于:分组排序只做一次,后续每个订单的匹配都是O(logn)的时间复杂度,数据量越大,效率提升越明显。
两种方法都能得到你想要的结果,根据你的数据规模选合适的就行~
备注:内容来源于stack exchange,提问作者Ch2231
相关产品推荐
相关产品推荐

