You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Numpy.strides重实现带重置的滚动求和?

无循环实现带重置的滚动求和(NumPy)

你的需求是每window_size个元素就重置求和,从头开始累加,以下是两种无需循环的高效实现方式,性能远优于原循环方法:

方法一:分块累积和(简单直观)

这种方法通过将数组按窗口大小分块,对每块计算累积和后拼接结果,逻辑清晰且无需复杂操作:

def rolling_sum_with_reset_block(arr, window_size):
    arr = np.asarray(arr)
    # 补全数组长度至window_size的整数倍(补0不影响求和结果)
    pad_length = (window_size - len(arr) % window_size) % window_size
    padded_arr = np.pad(arr, (0, pad_length), mode="constant")
    # 分块并计算每块的累积和
    block_cumsum = np.cumsum(padded_arr.reshape(-1, window_size), axis=1)
    # 展平后截取原数组长度的结果
    return block_cumsum.flatten()[:len(arr)]

方法二:使用np.lib.stride_tricks.as_strided

如果一定要用stride_tricks,可以通过创建数组视图来实现分块(本质和分块法逻辑一致,但利用了视图避免数据复制):

def rolling_sum_with_reset_strided(arr, window_size):
    arr = np.asarray(arr)
    n = len(arr)
    n_full_blocks = n // window_size
    remainder = n % window_size

    # 处理完整窗口块:用strided创建视图
    full_block_view = np.lib.stride_tricks.as_strided(
        arr[:n_full_blocks * window_size],
        shape=(n_full_blocks, window_size),
        strides=(arr.strides[0] * window_size, arr.strides[0])
    )
    full_cumsum = np.cumsum(full_block_view, axis=1).flatten()

    # 处理剩余不足一个窗口的元素
    if remainder > 0:
        rem_cumsum = np.cumsum(arr[n_full_blocks * window_size:])
        return np.concatenate([full_cumsum, rem_cumsum])
    return full_cumsum

验证与性能

两种方法的结果和原循环函数完全一致:

original_result = rolling_sum_with_reset(apple_volume, 3)
block_result = rolling_sum_with_reset_block(apple_volume, 3)
strided_result = rolling_sum_with_reset_strided(apple_volume, 3)

print(np.array_equal(original_result, block_result))  # 输出 True
print(np.array_equal(original_result, strided_result))  # 输出 True

在大数据量场景下,向量运算的方法比循环快数十倍,尤其适合处理长时序数据。

内容的提问来源于stack exchange,提问作者Merlin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 02:51:27