如何高效对Pandas列300万条数据计算距俄罗斯法定假日的最近天数
问题核心瓶颈
你当前写法耗时过高主要有两个原因:
- 用Python原生循环逐行处理300万条数据,单步循环开销极高
- 每次循环都全量遍历法定假日列表计算差值,时间复杂度为O(数据行数*假日数量),数据规模上去后耗时会指数级增长
最优解决方案(向量化实现,秒级跑完300万行)
推荐用Pandas内置的merge_asof实现全向量化匹配,完全避免Python原生循环,性能提升几个数量级:
import pandas as pd # 第一步:预处理法定假日列表,转为DataFrame并按日期排序(merge_asof要求右表排序) holidays_df = pd.DataFrame({ 'holiday_date': russian_public_holidays }).sort_values('holiday_date', ignore_index=True) # 第二步:给原训练数据加临时索引,匹配后可以恢复原始顺序 training_data = training_data.reset_index().sort_values('date', ignore_index=True) # 第三步:反向匹配最近的未来法定假日 merged = pd.merge_asof( left=training_data, right=holidays_df, left_on='date', right_on='holiday_date', direction='forward' # 匹配大于等于当前日期的最近假日,符合你的需求 ) # 第四步:计算间隔天数,恢复原始数据顺序 merged['closest_public_holiday'] = (merged['holiday_date'] - merged['date']).dt.days training_data = merged.sort_values('index').drop(columns=['index', 'holiday_date']).reset_index(drop=True)
如果存在部分日期晚于所有法定假日的情况,计算结果会出现NaN,可以按需用fillna填充默认值即可。
备选方案(二分查找+日期去重,适合小体量假日列表)
如果你的数据中重复日期非常多,也可以先对日期去重后用二分查找计算,再映射回原表:
import bisect import numpy as np # 预处理法定假日为排序后的日期数组 holidays_sorted = np.sort(np.array(russian_public_holidays, dtype='datetime64[D]')) # 提取所有唯一日期 unique_dates = training_data['date'].dt.date.unique() unique_dates_arr = np.array(unique_dates, dtype='datetime64[D]') # 批量计算唯一日期的间隔天数 delta_map = {} for d, d_arr in zip(unique_dates, unique_dates_arr): idx = bisect.bisect_left(holidays_sorted, d_arr) if idx < len(holidays_sorted): delta_map[d] = int(holidays_sorted[idx] - d_arr) else: delta_map[d] = -1 # 晚于所有假日的默认返回值,可自行修改 # 映射回原数据集 training_data['closest_public_holiday'] = training_data['date'].dt.date.map(delta_map)
内容的提问来源于stack exchange,提问作者Kailash Gautham
相关产品推荐
相关产品推荐

