在Pandas rolling函数中纳入NaN计算窗口大小与min_periods求滚动均值
解决方案
可以通过结合滚动求和、滚动计数,再配合窗口元素总数的判断来实现,完全无需循环,步骤如下:
- 定义窗口参数:
window_size = 5 min_periods = 4
- 构造示例DataFrame并计算滚动总和、滚动非NaN值计数:
import pandas as pd import numpy as np df = pd.DataFrame( {'U': [np.nan, np.nan, -0.068554, -0.056425, -0.022294, -0.038996, -0.026863]}, index=pd.to_datetime(['1990-02-28', '1990-03-01', '1990-03-02', '1990-03-05', '1990-03-06', '1990-03-07', '1990-03-08']) ) # 滚动求和(自动忽略NaN,只统计非NaN值的和) roll_sum = df['U'].rolling(window=window_size, min_periods=1).sum() # 滚动计数(统计窗口内非NaN值的数量) roll_count = df['U'].rolling(window=window_size, min_periods=1).count()
- 判断每个窗口是否满足总元素数(含NaN)≥min_periods:
# 生成每个位置对应的窗口总元素数:未达窗口大小时取当前已有的行数,达标后固定为窗口大小 total_elements = np.minimum(np.arange(len(df)) + 1, window_size) # 生成掩码:仅当总元素数≥min_periods时才计算均值 mask = total_elements >= min_periods
- 计算目标滚动均值,不满足条件的位置设为NaN:
df['rolling_mean'] = np.where(mask, roll_sum / roll_count, np.nan)
验证结果
运行后得到的DataFrame与预期完全一致:
U rolling_mean date 1990-02-28 NaN NaN 1990-03-01 NaN NaN 1990-03-02 -0.068554 NaN 1990-03-05 -0.056425 -0.062489 1990-03-06 -0.022294 -0.049091 1990-03-07 -0.038996 -0.046567 1990-03-08 -0.026863 -0.042626
逻辑说明
- 滚动求和与计数:利用Pandas内置
rolling方法自动忽略NaN,保证均值计算的准确性; - 窗口总元素数判断:通过
np.minimum生成每个位置的窗口实际总行数(含NaN),再与min_periods对比,确定可计算均值的位置; - 条件赋值:用
np.where实现按需赋值,不满足条件的位置直接设为NaN。
内容的提问来源于stack exchange,提问作者younggotti
相关产品推荐
相关产品推荐

