需求:
构建ARIMA(p,d,q)模型首先根据时间序列的折线图对序列进行初步的平稳性判断,并采用ADF单位根对序列的平稳性进行检验,对非平稳的时间序列,进行差分处理,直至成为平稳序列,差分的次数即为模型阶数d。利用一阶差分后的新序列进行自相关和偏自相关分析,并绘制自相关系数图和偏自相关系数图,再基于AIC和BIC最小化原则进行自动筛选,最终判断出ARIMA(p,d,q)模型中的参数p、q,即得到最终的预测模型。
实战案例:
现有6月1日(8:00-18:00)的值,需要利用ARIMA模型预测19:00-20:00的的值。
导入模块
#Copyright (c) 2021 XiaoxiaoLiang. All rights reserved.
import warnings
warnings.filterwarnings("ignore")
import pandas as pd
import numpy as np
import matplotlib.pylab as plt
from matplotlib.pylab import style
style.use('ggplot')
from statsmodels.graphics.api import qqplot
pd.set_option('display.float_format', lambda x: '%.5f' % x)
np.set_printoptions(precision=5, suppress=True)
"""中文显示问题"""
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei']
加载数据
data = pd.read_excel("D:\Testnumber\一天数据\站点.xlsx",index_col="日期",parse_dates=True)
data.head()
print(data)
绘制时序图、自相关图和偏自相关图
#时序图
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
data.plot()
print(data)
# plt.show()
#自相关图
from statsmodels.graphics.tsaplots import plot_acf,plot_pacf
plot_acf(data).show()
plot_pacf(data).show()
# plt.show()
#平稳性检验、差分
#平稳性检验 其中PM2为列名
from statsmodels.tsa.stattools import adfuller as ADF
print( ADF(data[u'PM2']))
#返回值依次为adf、pvalue、usedlag、nobs、critical values、icbest、regresults、resstore
#差分
diff1 = data.diff(1).dropna()
diff2= diff1.diff(1).dropna()
diff3= diff2.diff(1).dropna()
diff1.plot(color='red', title='diff 1', figsize=(10, 4))
diff2.plot(color='black', title='diff 2', figsize=(10, 4))
# diff3.plot(color='black', title='diff 3', figsize=(10, 4))
#对差分以后的值进行平稳性检验
print(ADF(diff1[u'PM2']))
print(ADF(diff2[u'PM2']))
#发现一阶差分更好,所以选取一阶差分,d=1
#差分以后的时序图、自相关和偏自相关图
diff2.plot() # 时序图
plot_acf(diff1).show()
plot_pacf(diff1).show()
确定ARIMA(p,d,q)模型的p q值,多次运行取AIC和BIC最小的时候的值
# 参数估计
from statsmodels.tsa.arima_model import ARIMA
model = ARIMA(data, order=(1,1,0))#导入ARIMA模型
result = model.fit(disp=-1)
print(result.summary())
#模型检验 QQ图
resid = result.resid#残差
fig = plt.figure(figsize=(12,8))
ax = fig.add_subplot(111)
fig = qqplot(resid, line='q', ax=ax, fit=True)
预测并将预测值写入表格
# #最后画出时序图
pred = result.predict('2021/6/1 18:00:00', '2021/6/1 20:00:00',dynamic=True, typ='levels')
print (pred)
# print(result.forecast(5))
x = range(8,18)
xticks_label = [f"{i}:00" for i in x]
plt.figure(figsize=(12, 28))
plt.xticks(rotation=45)
plt.plot(pred)
plt.plot(data.PM2)
# plt.show()
#写入表格
writer = pd.ExcelWriter('D:\Testnumber\一天数据\PM2.5pre.xlsx')
pred.to_excel(writer)
writer.save()
writer.close()
plt.show()
关于foreast和predict的区别:
predict 可以对样本内和样本外的进行预测,结果是一样的。
举例说明:forecast(10),表示对未来10个点进行预测,但是可以用model.fittedvalues查看样本内点的拟合值;
而predict(start,end)里面的参数0表示样本内的第一个数,以此类推。
如果想要预测样本外的数,需要将start设置为len(data)+1,即数据长度+1,才表示预测样本外的第一个数字。
而 forecast函数,是对样本外的数据进行预测。
但是这两个函数的预测结果是一样的。
ADF结果如何查看参考了这篇博客:
ADF结果
参考博客:
ARIMA模型
一切文章皆为原创,转载请注明来源@小小梁的实验室