本文介绍如何对 pandas dataframe 的所有列联合计算滚动标准差,自动忽略 nan 值,并支持自定义窗口大小和自由度校正(ddof),适用于多列混合缺失值的场景。
本文介绍如何对 pandas dataframe 的所有列联合计算滚动标准差,自动忽略 nan 值,并支持自定义窗口大小和自由度校正(ddof),适用于多列混合缺失值的场景。
在实际数据分析中,常需跨列聚合计算滚动统计量(如标准差),而非逐列独立计算。当数据含大量缺失值(NaN)时,直接使用 df.rolling().std() 仅作用于每列内部,无法实现“将当前窗口内所有非空数值视为一个整体样本集”的需求——而这正是本例的核心目标:对每个滚动窗口内所有列的所有有效值(忽略 NaN)统一计算样本标准差。
解决方案的关键在于绕过 Pandas 原生滚动 API 的列隔离限制,转而借助 NumPy 的底层能力:
- 使用 df.to_numpy() 获取数值矩阵;
- 利用 numpy.lib.stride_tricks.sliding_window_view 构建三维滑动窗口([window, row, col]);
- 对每个窗口沿 (1,2) 轴(即行与列维度)应用 np.nanstd(..., ddof=1),自动跳过 NaN 并按贝塞尔校正(样本标准差)计算。
以下是完整可执行代码:
import pandas as pd
import numpy as np
from numpy.lib.stride_tricks import sliding_window_view as swv
# 构造示例数据
data = {'a': {1: None, 2: 1, 3: 7, 4: 2, 5: 4},
'b': {1: None, 2: 2, 3: 2, 4: 9, 5: 6},
'c': {1: None, 2: 2.0, 3: None, 4: 7.0, 5: 4.0}}
df = pd.DataFrame(data).rename_axis('day')
# 设置窗口大小
N = 3
# 计算跨列滚动标准差(忽略 NaN,ddof=1)
# 注意:sliding_window_view 生成形状为 (n_windows, N, n_cols) 的数组
# np.nanstd(..., axis=(1,2)) 沿最后两维(即窗口内所有元素)计算
std_values = np.nanstd(swv(df.to_numpy(), window_shape=N, axis=0), axis=(1, 2), ddof=1)
# 将结果赋值到新列,对齐索引(前 N-1 行为 NaN)
df['std'] = np.nan
df.loc[df.index[N-1]:, 'std'] = std_values
print(df)
✅ 输出结果与预期一致:
a b c std day 1 NaN NaN NaN NaN 2 1.0 2.0 2.0 NaN 3 7.0 2.0 NaN 2.387467 4 2.0 9.0 7.0 3.116775 5 4.0 6.0 4.0 2.531939
? 验证第三行(day=3):窗口覆盖 day=1~3,对应数据为
[[NaN, NaN, NaN], [1.0, 2.0, 2.0], [7.0, 2.0, NaN]] → 有效值为 [1, 2, 2, 7, 2],
np.std([1,2,2,7,2], ddof=1) ≈ 2.387467,完全吻合。
⚠️ 注意事项:
- sliding_window_view 要求 NumPy ≥ 1.20;旧版本请升级或改用 np.lib.stride_tricks.as_strided(需手动处理步长);
- 该方法默认按行优先顺序展开窗口内所有值,天然兼容任意列数与缺失模式;
- 若需 min_periods=2(即至少 2 个非空值才计算),np.nanstd 默认行为已满足:当有效值数量
- 如需其他聚合(如滚动均值、分位数),可替换为 np.nanmean、np.nanquantile 等对应函数。
此方案兼顾性能与准确性,是处理跨列滚动统计 + 缺失值混合场景的推荐实践。











