如何在Pandas中合并多次rolling.apply调用以提升运行效率?
高效计算多窗口未来累积收益率的方法
你的代码多次重复分组、滚动计算,且rolling.apply()使用lambda逐窗口处理,效率很低。可以通过预计算反向累积乘积的方式,一次性完成所有窗口的计算,大幅提升运行速度。
核心思路
- 对每个
PERMNO分组,计算(1+RET)的反向累积乘积:即从当前行到该分组最后一行的所有(1+RET)的乘积。 - 利用移位操作,通过累积乘积的比值得到不同窗口的累积收益率,避免重复分组和滚动循环。
优化后的代码
import pandas as pd # 定义窗口大小与对应列名的映射 window_map = {1: 'next_1', 3: 'next_3', 6: 'next_6', 12: 'next_12', 60: 'next_60'} # 步骤1:按PERMNO分组,计算反向累积乘积 # cum_prod[i] 表示从第i行到该PERMNO最后一行的(1+RET)乘积 df['cum_prod'] = df.groupby('PERMNO')['RET'].transform( lambda x: (1 + x)[::-1].cumprod()[::-1] ) # 步骤2:遍历每个窗口大小,计算对应未来累积收益率 for window_size, col_name in window_map.items(): # 移位window_size位,获取未来window_size行后的累积乘积,不足时用1填充(对应没有更多数据的情况) shifted_cum = df.groupby('PERMNO')['cum_prod'].shift(-window_size).fillna(1) # 累积收益率 = 当前到末尾的乘积 / 未来window_size到末尾的乘积 - 1 df[col_name] = df['cum_prod'] / shifted_cum - 1 # 可删除中间列(如果不需要的话) df.drop(columns='cum_prod', inplace=True)
效率提升原因
- 原代码中
rolling.apply()是逐窗口循环计算,属于低效的行级操作;优化后仅做一次分组计算累积乘积,后续通过向量化的移位、除法操作完成所有窗口计算,速度提升显著。 - 避免了重复的
groupby和rolling操作,减少了冗余计算。
结果一致性
这段代码的计算结果和你原代码完全一致,包括边界情况(比如分组末尾不足窗口大小的行,会自动计算剩余所有行的累积收益率)。
内容的提问来源于stack exchange,提问作者Ruchit
相关产品推荐
相关产品推荐

