ARIMA模型预测周度销售数据时Matplotlib绘图报错求助
背景情况
我使用SARIMAX(ARIMA类模型)预测某产品销量,数据为2015-01-01至2016-11-24的周度销售数据(CSV格式),需预测未来9周的销量。代码在月度数据上运行正常,但处理周度数据时绘图阶段出现错误。
CSV数据示例
"01-01-2015",9 "08-01-2015",8 "15-01-2015",13 "22-01-2015",10 "29-01-2015",12 "05-02-2015",5 "12-02-2015",4 "19-02-2015",6 "26-02-2015",9 "05-03-2015",3 "12-03-2015",3 "19-03-2015",2 ...
使用的代码
def parser(x): return datetime.datetime.strptime(x, '%d-%m-%Y') fn = 'filename.csv' y = pd.read_csv(fn, header = 0, parse_dates = [0], index_col = 0, squeeze = True, date_parser = parser) newmod = sm.tsa.statespace.SARIMAX(y,order=(1, 1, 0),seasonal_order=(1, 1, 0, 12),enforce_stationarity=False,enforce_invertibility=False) newresults = newmod.fit() pred_uc = newresults.get_forecast(steps = 9) pred_ci = pred_uc.conf_int() y1 = pred_ci.iloc[:,0] y2 = pred_ci.iloc[:,1] ax = y.plot(label = "observed") pred_uc.predicted_mean.plot(ax=ax, label='Forecast') ax.fill_between(pred_ci.index, pred_ci.iloc[:,0],pred_ci.iloc[:,1], color = 'k' , alpha = 0.5) ax.set_xlabel('Date') ax.set_ylabel('Sales count') plt.legend() plt.show()
报错信息
Traceback (most recent call last): File "H:\p36564\fit_net1.py", line 57, in <module> pred_uc.predicted_mean.plot(ax=ax, label='Forecast') File "H:\p36564\lib\site-packages\pandas\plotting\_core.py", line 2503, in __call__ **kwds) File "H:\p36564\lib\site-packages\pandas\plotting\_core.py", line 1927, in plot_series **kwds) File "H:\p36564\lib\site-packages\pandas\plotting\_core.py", line 1729, in _plot plot_obj.generate() File "H:\p36564\lib\site-packages\pandas\plotting\_core.py", line 258, in generate self._post_plot_logic_common(ax, self.data) File "H:\p36564\lib\site-packages\pandas\plotting\_core.py", line 396, in _post_plot_logic_common fontsize=self.fontsize) File "H:\p36564\lib\site-packages\pandas\plotting\_core.py", line 470, in _apply_axis_properties labels = axis.get_majorticklabels() + axis.get_minorticklabels() File "H:\p36564\lib\site-packages\matplotlib\axis.py", line 1245, in get_majorticklabels ticks = self.get_major_ticks() File "H:\p36564\lib\site-packages\matplotlib\axis.py", line 1396, in get_major_ticks numticks = len(self.get_major_locator()()) File "H:\p36564\lib\site-packages\matplotlib\dates.py", line 1249, in __call__ self.refresh() File "H:\p36564\lib\site-packages\matplotlib\dates.py", line 1269, in refresh dmin, dmax = self.viewlim_to_dt() File "H:\p36564\lib\site-packages\matplotlib\dates.py", line 1026, in viewlim_to_dt .format(vmin)) ValueError: view limit minimum -36710.65 is less than 1 and is an invalid Matplotlib date value. This often happens if you pass a non-datetime value to an axis that has datetime units.
问题根源与解决办法
这个报错的核心原因其实很清晰:你给SARIMAX指定的季节性周期与周度数据不匹配,导致预测结果的索引不是合法的日期格式。
1. 修正季节性周期参数
你当前的seasonal_order=(1,1,0,12)里,最后一个参数12是月度数据的季节性周期(一年12个月),但周度数据的季节性周期应该是52(一年约52周)。把这个参数改成52,也就是seasonal_order=(1,1,0,52),这是解决问题的关键。
为什么这会引发绘图错误?因为当周期参数不匹配时,SARIMAX生成的预测索引可能无法正确解析为datetime类型,或者计算出的日期超出了Matplotlib可识别的日期范围,最终触发"无效日期值"的报错。
2. 额外验证与修复步骤
除了修改周期参数,你还可以做以下几步确保数据和预测索引的正确性:
- 检查原始数据索引类型:运行
print(y.index.dtype),确认输出是datetime64[ns],确保时间序列的索引格式正确。 - 查看预测结果的索引:运行
print(pred_uc.predicted_mean.index),确认这些日期是原始数据结束日期之后的连续9周,且为合法的datetime格式。 - 如果索引仍有问题,可以手动生成未来日期并赋值:
# 获取原始数据的最后一个日期 last_date = y.index[-1] # 生成未来9周的日期序列(从下一周开始) future_dates = pd.date_range(last_date, periods=10, freq='W')[1:] # 给预测结果和置信区间设置正确的索引 pred_uc.predicted_mean.index = future_dates pred_ci.index = future_dates
3. 检查CSV数据格式
你的CSV数据示例看起来是用空格分隔每个日期-销量对,这不符合标准CSV的格式(通常每行一条数据,或用逗号分隔字段)。如果你的原始CSV确实是这种格式,pd.read_csv可能无法正确解析数据,导致索引或数值异常。你可以检查y的结构(比如print(y.head())),确保它是一个正确的时间序列。如果解析有问题,可以调整pd.read_csv的参数,比如指定sep=' '来分隔数据。
修改季节性周期参数后,重新运行代码,应该就能正常完成绘图了。
内容的提问来源于stack exchange,提问作者Arkistarvh Kltzuonstev

