Python时间序列销售预测中,滚动均值计算如何忽略NaN值?
嘿,我完全懂你遇到的困扰——在做时间序列销售预测时,想计算过去3天的平均销量特征,但未来日期的销量是NaN,导致滚动窗口只要包含NaN就输出NaN,根本达不到预期效果。别担心,这其实是Pandas滚动方法的参数设置问题,我来一步步帮你解决!
首先要提一句:pd.rolling_mean()这个函数在Pandas 0.18.0版本之后就被弃用了,现在推荐使用更灵活的rolling()方法搭配mean(),这也是我们解决问题的核心工具。
步骤1:构造你的数据(方便演示)
先把你给出的数据转换成Pandas DataFrame,并且把日期列转成时间格式:
import pandas as pd import numpy as np # 构造你的数据 data = { 'Date': ['02-01-2013', '03-01-2013', '04-01-2013', '05-01-2013', '06-01-2013'], 'Sales': [100.0, 200.0, 300.0, 200.0, np.nan] } df = pd.DataFrame(data) # 转换日期格式 df['Date'] = pd.to_datetime(df['Date'], format='%d-%m-%Y')
步骤2:问题根源分析
你遇到的“窗口有NaN就输出NaN”,是因为默认情况下rolling().mean()的min_periods参数等于窗口大小(也就是3)——意思是只有当窗口内有3个非NaN值时才计算均值,否则输出NaN。而未来日期的Sales是NaN,导致窗口内有效值不足3个,所以结果变成NaN。
步骤3:两种解决方案
方案一:允许忽略NaN,计算现有有效值的平均
通过skipna=True(默认就是这个值,不过可以显式写出来更清晰),让Pandas忽略窗口内的NaN,用剩下的有效值计算均值:
# 计算过去3天平均,忽略窗口内的NaN df['3d_avg'] = df['Sales'].rolling(window=3, skipna=True).mean()
这样对于06-01的行,窗口包含300、200、NaN,会计算(300+200)/2 = 250,而不是NaN。
方案二:设置最小有效值数量
如果你希望窗口内至少有N个有效值才计算均值,可以调整min_periods参数。比如要求至少2个有效值:
# 窗口内至少有2个非NaN值才计算均值 df['3d_avg_min_periods'] = df['Sales'].rolling(window=3, min_periods=2).mean()
这个设置下,只要窗口内有2个及以上的非NaN值,就会输出均值,完美适配你未来日期的场景。
最终结果示例
运行上述代码后,你的DataFrame会变成这样:
| Date | Sales | 3d_avg | 3d_avg_min_periods |
|---|---|---|---|
| 2013-01-02 | 100.0 | NaN | NaN |
| 2013-01-03 | 200.0 | NaN | NaN |
| 2013-01-04 | 300.0 | 200.0 | 200.0 |
| 2013-01-05 | 200.0 | 233.333 | 233.333 |
| 2013-01-06 | NaN | 250.0 | 250.0 |
这样就完全符合你构建过去3天平均销量特征的需求了!
内容的提问来源于stack exchange,提问作者Ron

