目标是预测未来三期传统汽车的销量。
数据背景:
03年到19年第一季度分季度的数据,13年之前只有传统汽车的销量,13年之后是传统汽车+新能源汽车的销量,需要预测未来三期传统汽车的销量~
ps:传统汽车的销量会受到新能源汽车的影响噢~
(我们先针对传统销量进行时间序列预测,不考虑新能源汽车)
import numpy as np
import pandas as pd
import datetime
import matplotlib.pyplot as plt
import statsmodels.api as sm
from dateutil.relativedelta import relativedelta
from statsmodels.tsa.seasonal import seasonal_decompose
#首先处理下数据
data=pd.read_excel("/Downloads/data.xlsx",index_col=0)
print(data.head(10))
data.index.name = None # 将index的name取消
data.reset_index(inplace=True)
data.drop(data.index[64], inplace=True)
start = datetime.datetime.strptime("2003-01", "%Y-%m") # 把一个时间字符串解析为时间元组
date_list = [start + relativedelta(months=x*3) for x in range(0, 64)] # 从2003-01-01开始逐月增加组成list
data['index'] = date_list
data.set_index(['index'], inplace=True)
print(data.head(10))
传统汽车销量 国内生产总值当季值(亿元)x1 ... 汽车整车股票指数 消费者信心指数
index ...
2003-01-01 102.1 29825.5 ... 1696.81 97.700000
2003-04-01 110.0 32537.3 ... 1912.54 87.666667
2003-07-01 112.1 35291.9 ... 1803.71 92.333333
2003-10-01 122.8 39767.4 ... 1922.48 94.666667
2004-01-01 131.1 34544.6 ... 1930.71 95.333333
2004-04-01 133.3 38700.8 ... 1245.70 92.566667
2004-07-01 121.0 41855.0 ... 1163.16 91.066667
2004-10-01 123.7 46739.8 ... 870.61 92.566667
2005-01-01 139.7 40453.3 ... 749.62 93.933333
2005-04-01 162.2 44793.1 ... 764.84 94.533333
data1 = np.array(data['传统汽车销量'], dtype=np.float)
# 生成时间序列并画图
data1 = pd.Series(data1)
data1.index = data.index
# 趋势
data1.plot(figsize=(12, 8), title='传统汽车销量')
有明显的递增趋势,可以判断是非平稳的,再来看看是否有季节性
decomposition = seasonal_decompose(data['传统汽车销量'], freq=12)
fig = decomposition.plot()
fig.set_size_inches(15, 8)
具有明显的季节性波动,ARIMA 模型对时间序列的要求是平稳型。因此,当得到一个非平稳的时间序列时,首先要做的即是做时间序列的差分,直到得到一个平稳时间序列。
将数据平稳化,用简单的二阶差分:
fig = plt.figure(figsize=(12, 8))
ax2 = fig.add_subplot(111)
diff2 = data1.diff(2)
diff2.plot(ax=ax2)
模型选择
arma_mod70 = sm.tsa.ARMA(data1,(7,0)).fit()
print(arma_mod70.aic,arma_mod70.bic,arma_mod70.hqic)
arma_mod30 = sm.tsa.ARMA(data1,(0,1)).fit()
print(arma_mod30.aic,arma_mod30.bic,arma_mod30.hqic)
arma_mod71 = sm.tsa.ARMA(data1,(7,1)).fit()
print(arma_mod71.aic,arma_mod71.bic,arma_mod71.hqic)
arma_mod80 = sm.tsa.ARMA(data1,(8,0)).fit()
print(arma_mod80.aic,arma_mod80.bic,arma_mod80.hqic)
741.7064371640738 761.1363849143108 749.3608750397088
824.035997236598 830.512646486677 826.5874765284763
744.7216708631242 766.310501696721 753.226601836052
742.0032319184199 763.5920627520167 750.5081628913478
可以看出ARMA(7,0) 和ARMA(8,0) 是差不多的 ,这里选择两个对结果没有太大影响。
预测:
predict_dta = arma_mod70.predict('2019', '2022', dynamic=True)
print(predict_dta)
fig, ax = plt.subplots(figsize=(12, 8))
ax = data1.ix['2000':].plot(ax=ax)
fig = arma_mod70.plot_predict('2019', '2022', dynamic=True, ax=ax, plot_insample=False)
2019-01-01 713.995452
2019-04-01 621.508277
2019-07-01 595.797997
2019-10-01 637.025889
2020-01-01 647.507010
2020-04-01 620.106297
2020-07-01 594.112870
2020-10-01 597.800678
2021-01-01 613.221781
2021-04-01 605.209659
2021-07-01 585.717920
2021-10-01 581.768503
2022-01-01 587.753080
参考:《统计学(第七版)》贾俊平
(https://mp.weixin.qq.com/s/Whq2djsu6jhMmlgoLLNSEw)