如何通过向量化(Numpy)或其他方法加速Python合并循环代码?
代码优化方案:从1小时/120次到可支持365次循环
核心问题分析
原代码的性能瓶颈在于循环内重复执行merge和列重命名:每次循环的merge都是O(n log n)的耗时操作,365次循环会导致时间复杂度爆炸;同时重复的列重命名完全是冗余操作,进一步拖慢速度。
下面是针对性的优化方案:
1. 向量化生成所有DateX列
原循环中DateX_i = DateX_{i-1} + Tenor的递推逻辑,可以直接转化为初始日期 + i倍Tenor天数的向量化计算,一次性生成所有需要的DateX列:
# 获取初始日期列和Tenor对应的时间差 base_date = df['DateX0'] tenor_delta = pd.to_timedelta(df['Tenor'], unit='d') # 一次性生成DateX1到DateX365 for i in range(1, 366): df[f'DateX{i}'] = base_date + tenor_delta * i
此步骤避免了循环内逐列依赖计算的开销,计算效率提升数倍。
2. 重构df2为快速查找结构
把df2转换成以(Tenor, DateX)为复合索引的Series,用索引查找替代低效的merge:
# 先处理df2:如果是宽表(多DateXk/Ratek列),转成标准长表 if any('DateX' in col for col in df2.columns): # 拆分DateX列 datex_melt = pd.melt(df2, id_vars=['Tenor'], value_vars=[col for col in df2.columns if 'DateX' in col], var_name='date_col', value_name='DateX') # 匹配对应的Rate列 datex_melt['rate_col'] = datex_melt['date_col'].str.replace('DateX', 'Rate') # 合并Rate值 rate_melt = pd.melt(df2, id_vars=['Tenor'], value_vars=[col for col in df2.columns if 'Rate' in col], var_name='rate_col', value_name='Rate') df2_long = datex_melt.merge(rate_melt, on=['Tenor', 'rate_col']) # 去重并保留核心列 df2_long = df2_long[['Tenor', 'DateX', 'Rate']].drop_duplicates() # 设置复合索引,用于快速查找 rate_lookup = df2_long.set_index(['Tenor', 'DateX'])['Rate'] # 排序索引进一步提升查找速度 rate_lookup = rate_lookup.sort_index()
3. 批量生成所有Rate列
利用复合索引的快速查找能力,一次性匹配所有DateX对应的Rate值:
for i in range(1, 366): # 构造匹配用的复合索引 lookup_idx = pd.MultiIndex.from_frame(df[['Tenor', f'DateX{i}']]) # 批量查找并赋值 df[f'Rate{i-1}'] = rate_lookup.reindex(lookup_idx).values
此步骤用O(n)的批量查找替代了365次O(n log n)的merge,性能提升最为显著。
优化效果说明
- 时间复杂度从原代码的O(k * n log n)(k为循环次数)降至O(n + k*n),365次循环的运行时间可压缩至数分钟级别。
- 完全避免了冗余的列重命名操作,减少了内存开销。
内容的提问来源于stack exchange,提问作者Omerge
相关产品推荐
相关产品推荐

