旧版Pandas(0.13.1)替代pd.rolling实现年度收益计算方案
解决Pandas 0.13.1中无rolling方法的年度对数收益率计算问题
你遇到的问题确实是因为Pandas 0.13.1还没引入rolling() API(这个功能要到0.18.0版本才上线)。不用升级的话,我们可以用Numpy的滑动窗口技巧或者纯Pandas的apply方法来实现相同效果,下面是两种可行方案:
方案一:用Numpy stride_tricks实现高效滚动求和(推荐)
对于你这种10000行×900列的大尺寸DataFrame,Numpy的底层实现会比纯Pandas操作快很多,适合处理大规模数据:
import numpy as np import pandas as pd # 1. 将DataFrame转换为Numpy数组 arr = df_data_zero.values n_rows, n_cols = arr.shape window_size = 12 n_result_cols = n_cols - window_size + 1 # 计算结果的列数 # 2. 创建滑动窗口数组(利用stride_tricks避免数据复制,内存效率拉满) windowed_arr = np.lib.stride_tricks.as_strided( arr, shape=(n_rows, n_result_cols, window_size), strides=(arr.strides[0], arr.strides[1], arr.strides[1]) ) # 3. 对每个12期窗口求和,得到年度对数收益率 annual_returns_arr = windowed_arr.sum(axis=2) # 4. 转换回DataFrame,保留原索引和对应年度结束的列名 annual_returns_df = pd.DataFrame( annual_returns_arr, index=df_data_zero.index, columns=df_data_zero.columns[window_size-1:] # 第一个窗口对应前12个月,结束于第12列(索引11),所以列名从这里开始 )
小提示:
stride_tricks不会复制原始数据,只是改变数组的视图,所以内存占用极低- 列名可以根据你的业务需求调整,如果年度收益率需要对应窗口起始的月份,就把列名改成
df_data_zero.columns[:-window_size+1]
方案二:纯Pandas apply方法(兼容旧版本)
如果不想依赖Numpy的高级技巧,可以用Pandas的apply逐行处理,虽然效率略低,但完全兼容0.13.1版本:
import pandas as pd def calculate_annual_return(row, window_size=12): # 对单行计算所有连续12期的和 return [row[i:i+window_size].sum() for i in range(len(row)-window_size+1)] # 逐行应用函数,得到每个行的结果列表 row_results = df_data_zero.apply(calculate_annual_return, axis=1) # 将列表转换为DataFrame annual_returns_df = pd.DataFrame.from_records(row_results.values, index=row_results.index) # 设置对应的列名 annual_returns_df.columns = df_data_zero.columns[11:]
小提示:
- 对于10000行的数据,这个方法会比Numpy方案慢一些,但如果你的计算资源足够,完全可以正常运行
pd.DataFrame.from_records在Pandas 0.13.1中是原生支持的,不用担心版本兼容问题
两种方案都能实现你需要的连续12个月对数收益率求和的效果,根据你的性能需求选择即可。
内容的提问来源于stack exchange,提问作者gte
相关产品推荐
相关产品推荐

