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

如何在Pandas中计算带滚动掩码的滚动平均值(排除指定区间)

搞定带自定义掩码的滚动窗口计算需求

刚好碰到过类似的场景,咱们来一步步解决这个问题——核心就是要在滚动窗口里先过滤掉指定区间的数据,再做聚合计算,不管是简单均值还是复杂的非线性运算都能搞定。

最通用的方案:用rolling().apply()自定义过滤逻辑

这方法完全适配你说的非线性计算场景,思路很直接:给每个滚动窗口加个“过滤器”,先把要排除的数据筛掉,再执行你想要的计算。

针对你的需求,直接上代码:

import pandas as pd
import numpy as np

# 先生成你给的示例数据
idx = pd.date_range(start='2000', end='2001')
df = pd.DataFrame(np.random.normal(size=(len(idx), 2)), index=idx)

def masked_window_calc(window):
    """
    自定义滚动窗口计算函数:先排除指定区间,再算均值(可替换成任何计算)
    """
    # 拿到当前窗口的最后一个日期(也就是你说的每个目标日期t)
    end_date = window.index[-1]
    # 定义要排除的日期范围:t往前10天±2天,也就是t-12到t-8
    exclude_start = end_date - pd.Timedelta(days=12)
    exclude_end = end_date - pd.Timedelta(days=8)
    # 生成掩码:把排除区间内的数据标记为False,剩下的保留
    mask = ~((window.index >= exclude_start) & (window.index <= exclude_end))
    # 过滤后计算均值——这里换成ewm.mean()或者其他非线性计算都可以
    filtered_data = window[mask]
    return filtered_data.mean()

# 把自定义函数应用到60天滚动窗口上
df_avg = df.rolling(window=60).apply(masked_window_calc)

小细节说明:

  • 如果你的排除规则是基于窗口内的位置(比如固定排除窗口里第48到52位,不管日期),那可以改成用位置掩码,效率更高:
    def masked_window_calc(window):
        # 窗口长度是60,末尾是第59位(0索引),排除t-52到t-48对应位置是48到52
        mask = np.ones(len(window), dtype=bool)
        mask[48:53] = False  # 闭区间所以切片到53
        filtered_data = window[mask]
        return filtered_data.mean()
    
    # 加raw=True,直接传NumPy数组,速度更快
    df_avg = df.rolling(window=60).apply(masked_window_calc, raw=True)
    
  • 要是想换成指数加权平均,直接把filtered_data.mean()改成filtered_data.ewm(alpha=0.1).mean().iloc[-1]就行,完全不用改整体逻辑。

大数据集优化:预生成掩码矩阵

如果你的数据量很大,apply()可能有点慢,这时候可以用预生成掩码矩阵的方法,用NumPy向量化操作提速:

window_size = 60
# 生成一个(len(df), window_size)的矩阵,全是True,代表默认保留所有数据
mask_matrix = np.ones((len(df), window_size), dtype=bool)
# 把要排除的位置(第48到52列)改成False
mask_matrix[:, 48:53] = False

# 把DF转换成滚动窗口的数组,再用掩码过滤后求平均
rolling_array = df.rolling(window=window_size).apply(lambda x: x, raw=True).values.reshape(-1, window_size, 2)
df_avg = pd.DataFrame(
    np.mean(rolling_array * mask_matrix[window_size-1:][:, :, np.newaxis], axis=1),
    index=df.index[window_size-1:]
)

这个方法适合窗口长度固定的场景,速度比apply()快不少,因为用了NumPy的批量计算。

为啥不推荐“两个均值相减”?

你提到的那种方法,虽然在均值场景下能凑合用,但缺点很明显:

  • 只能处理线性计算(比如均值、求和),碰到中位数、方差或者自定义非线性函数就歇菜了
  • 规则稍微复杂一点(比如排除区间和窗口有重叠),很容易算错
  • 代码可读性差,以后维护起来得花时间理清楚逻辑

所以还是用上面两种通用方法更靠谱,不管需求怎么变都能适配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:34:44