小数值窗口的 skew、kurt 全是 NaN,检查 pandas 的方差阈值
数据有变化且窗口已满,Rolling.skew、kurt 却全是 NaN。说明小幅值触发绝对阈值的旧路径、3.1.0 修正和独立窗口对照。
五个样本的滚动窗口已经填满,值也不是常数,rolling(5).skew() 和 kurt() 却一直返回 NaN。若数据量级约为 1e-8,需要检查低方差窗口被绝对阈值判成退化分布的旧计算路径,而不只是降低 min_periods。
偏度和峰度是标准化形状统计,正常条件下整体正比例缩放不应改变它们。旧滚动实现用绝对小量判断二阶矩,数值幅度缩小后可能直接返回 NaN。pandas 3.1.0 已包含低方差窗口的对应修正;它不意味着真正的常数窗口也应返回有限偏度或峰度。
先把窗口不足与低方差分开
默认五点窗口的前四个位置没有足够观测,NaN 符合要求。问题在于窗口满了之后,仍把有变化的小幅值样本当作没有可计算形状。还应核对是否存在缺失值,以及原来的窗口类型、最小观测数和分组边界。
不要将所有 NaN 填为 0。零偏度是一种有效分布形状,零峰度也有具体定义,均不能代替“尚未计算”或“退化分布”。把 min_periods=1 也不会让一个样本拥有有效的无偏偏度。
在可控输入上逐窗口独立对照
下面用无缺失、非常数的浮点数据,比较相同五点窗口;SciPy 明确采用 bias=False 进行偏差修正:
import numpy as np
import pandas as pd
from scipy import stats
rng = np.random.default_rng(505)
s = pd.Series(rng.normal(0.0, 1e-8, 10))
window = s.rolling(5)
reference_skew = window.apply(lambda x: stats.skew(x, bias=False), raw=True)
reference_kurt = window.apply(
lambda x: stats.kurtosis(x, bias=False, fisher=True), raw=True
)
将参考结果与 window.skew()、window.kurt() 在相同位置比较。fisher=True 使用正态分布超额峰度为零的约定,与这里的 pandas 统计对应;不能拿 Pearson 峰度相差 3 的结果直接判为算法错误。
逐窗重新计算通常比原生滚动累加更耗时,可以用于小范围诊断或经过资源评估的暂时替代,不适合不计成本地替换所有长序列。真实输入含 NaN 时,还需明确两边的缺失值政策和有效样本数,不能直接套用这份无缺失示例。
更新后保留常数与不同量级样本
采用包含修正的正式 pandas 版本后,检查原有滚动入口,覆盖普通量级、小幅值、真正常数和窗口不足的输入。比较统计值与合理容差,同时确认窗口坐标和组边界没有变化。
任意放大数据、得到非 NaN 后再认为问题解决,会把正确性绑在某个经验尺度上。大偏置、小波动、溢出和缺失值还有不同的数值风险,不能用一个倍率统一处理。已经输出到报表或模型特征的 NaN,应依据原始输入与统计定义重算,不能只更新展示层。


