如何高效向量化实现Pandas DataFrame的日期后向填充?
高效向量化解决方案(基于Pandas)
针对大数据集场景,完全可以用Pandas的向量化操作替代循环,核心思路是先构建完整日期序列,再通过分组填充实现间隔日期的Preds赋值,全程避免Python层面的循环迭代。
步骤1:定义参数与原始数据示例
假设你的原始数据是每个Code对应一个START_DATE,以及各增量节点的预测值(如Pred_0对应increments[0]):
import pandas as pd import numpy as np # 增量列表 increments = [0, 3, 6, 10, 15, 21] max_increment = max(increments) # 示例原始数据(实际可替换为你的数据集) raw_df = pd.DataFrame({ 'Code': ['A', 'B', 'C'], 'START_DATE': pd.to_datetime(['2024-01-01', '2024-02-01', '2024-03-01']), 'Pred_0': [10, 5, 8], 'Pred_3': [12, 7, 9], 'Pred_6': [15, 9, 11], 'Pred_10': [18, 11, 14], 'Pred_15': [20, 13, 16], 'Pred_21': [22, 15, 19] })
步骤2:转换为长格式并生成预测节点日期
将宽表的Pred列转换为长格式,匹配对应的增量日期:
# 把多列Pred转换为长格式,提取增量数值 long_preds = raw_df.melt( id_vars=['Code', 'START_DATE'], var_name='Increment', value_name='Preds' ) # 从列名中提取增量数字(如Pred_3 → 3) long_preds['Increment'] = long_preds['Increment'].str.extract(r'(\d+)').astype(int) # 只保留increments列表中的有效增量 long_preds = long_preds[long_preds['Increment'].isin(increments)] # 计算每个增量对应的预测日期 long_preds['Pred_Date'] = long_preds['START_DATE'] + pd.to_timedelta(long_preds['Increment'], unit='D')
步骤3:生成每个Code的完整日期序列
为每个Code生成从START_DATE到START_DATE+max_increment的所有连续日期:
# 生成每个Code的日期范围序列 date_series = raw_df.apply( lambda row: pd.date_range( start=row['START_DATE'], end=row['START_DATE'] + pd.Timedelta(days=max_increment), freq='D' ), axis=1 ) # 展开为Code+日期的全量DataFrame full_dates = pd.DataFrame({ 'Code': np.repeat(raw_df['Code'], date_series.str.len()), 'Pred_Date': np.concatenate(date_series.values) }) # 关联回START_DATE字段 full_dates = full_dates.merge(raw_df[['Code', 'START_DATE']], on='Code', how='left')
步骤4:合并Preds并填充间隔日期
用**反向填充(bfill)**实现用后续预测值填充中间间隔日期,全程向量化:
# 合并预测值到全量日期表 testing_df = full_dates.merge( long_preds[['Code', 'Pred_Date', 'Preds']], on=['Code', 'Pred_Date'], how='left' ) # 按Code分组,反向填充空值(取后续最近的非空Preds) testing_df['Preds'] = testing_df.groupby('Code')['Preds'].bfill() # 调整列顺序为目标结构 testing_df = testing_df[['START_DATE', 'Code', 'Pred_Date', 'Preds']]
核心优势
- 所有操作均基于Pandas底层优化的向量化接口(C语言实现),比Python循环效率高10~100倍,适合百万级以上数据集。
- 分组填充逻辑清晰,避免了循环中复杂的条件判断。
- 若同一
Code对应多个START_DATE,只需将分组键改为['Code', 'START_DATE']即可兼容。
内容的提问来源于stack exchange,提问作者Lopez
相关产品推荐
相关产品推荐

