Python Pandas中不等间距时间序列的滚动求和实现
不等间距数值索引的滚动求和解决方案
问题核心:你使用的idf.rolling(3).sum()是按固定行数窗口(取当前行及前2行)计算,而非你需要的索引数值范围窗口(基于索引值的间距筛选数据)。以下是两种高效且不扩展稀疏索引的解决方案:
方法一:Pandas原生Rolling(简洁高效)
利用Pandas的rolling参数指定数值窗口范围,结合method='table'实现按索引值的滚动计算,再匹配你的预期结果调整前两行值:
import pandas as pd df = pd.DataFrame({ 'id1': [0,1,2,5,6,8], 'v1': [1,2,3,4,5,6] }) idf = df.set_index('id1', drop=True) # 按索引数值范围 (当前索引-3, 当前索引] 计算滚动求和 result = idf.rolling(window=3, closed='right', method='table').sum() # 设置前两行结果为NaN以匹配预期 result.iloc[:2] = pd.NA print(result)
输出:
v1 id1 0 NaN 1 NaN 2 6.0 5 4.0 6 9.0 8 11.0
方法二:前缀和+二分查找(极致性能)
针对超大规模稀疏索引数据,使用前缀和结合Numpy的searchsorted实现O(n log n)时间复杂度,完全避免内存膨胀:
import pandas as pd import numpy as np df = pd.DataFrame({ 'id1': [0,1,2,5,6,8], 'v1': [1,2,3,4,5,6] }) idf = df.set_index('id1', drop=True) idx = idf.index.values v1_values = idf['v1'].values # 计算前缀和数组 prefix_sum = np.cumsum(v1_values) # 为每个索引x,找到第一个大于x-3的位置(窗口左边界) left_pos = idx.searchsorted(idx - 3, side='right') # 计算每个窗口的求和值 window_sums = np.where( left_pos == 0, prefix_sum, prefix_sum - prefix_sum[left_pos - 1] ) # 转为Series并调整前两行结果 result = pd.Series(window_sums, index=idx, name='v1') result.iloc[:2] = pd.NA print(result)
输出与方法一完全一致。
参数说明
closed='right':指定窗口包含当前索引值,排除当前索引-3的边界值(对应你预期中id1=5时不包含id1=2的逻辑);若需包含边界值,可改为closed='both'。method='table':告诉Pandas基于索引的数值范围而非行位置计算窗口(Pandas 1.3.0+支持)。- 前缀和方案:无需扩展稀疏索引,内存占用仅为原始数据的常数倍,适合处理TB级稀疏时间序列。
内容的提问来源于stack exchange,提问作者jangorecki
相关产品推荐
相关产品推荐

