如何高效计算DataFrame中忽略NaN的滞后30日滚动均值
解决滚动均值忽略NaN的高性能方案
嘿,这个问题我之前处理时间序列的时候也遇到过,其实完全不用绕到apply方法,pandas的rolling本身就有参数能完美解决,而且性能拉满,还不会碰你原数据里的NaN!
问题根源
你之前用df.rolling(window=30).mean().shift(1)出现大量NaN,核心原因是默认的min_periods参数设置:
rolling的mean()方法默认min_periods=window(也就是这里的30),意思是只有当窗口内的30个值全都是非NaN的时候,才会计算均值;只要有1个NaN,就返回NaN。这就是为什么你看到大量缺失值。
高性能解决方案
只需要给rolling加上min_periods参数,指定窗口内至少需要多少个非NaN值就计算均值,剩下的NaN会自动被忽略:
# 假设你的数据列名为value,这里设置min_periods=1表示只要窗口内有至少1个非NaN值就计算均值 df['rolling_30d_mean'] = df['value'].rolling(window=30, min_periods=1).mean().shift(1)
细节调整
- 如果你觉得
min_periods=1太宽松(比如不想用1个数据就计算均值),可以改成你需要的阈值,比如min_periods=20,表示窗口内至少要有20个非NaN值才输出均值,否则返回NaN,这样结果更严谨。 - 如果你是基于日期索引的时间序列,也可以用
window='30D'来指定时间窗口,配合min_periods同样生效,比如:df['rolling_30d_mean'] = df['value'].rolling(window='30D', min_periods=1).mean().shift(1)
为什么这个方案高性能?
这是pandas的原生向量化操作,底层是用C实现的,比apply这种逐行处理的Python级操作快几个数量级,完全符合你要的高性能要求,而且全程不会修改原数据里的NaN,完美匹配你的需求。
内容的提问来源于stack exchange,提问作者eternity1




