Q:
03年到19年第一季度分季度的数据,13年之前只有传统汽车的销量,13年之后是传统汽车+新能源汽车的销量,需要预测未来三期传统汽车的销量~ps:传统汽车的销量会受到新能源汽车的影响.
import pandas as pd import matplotlib.pyplot as plt data = pd.read_excel("C:orange_creditcrdt时序数据.xlsx", sheet_name='Sheet2', index_col=u'日期') #先画出日期和传统车型销量的图形,可以判断是非平稳的 data.plot() plt.show()
df.index.name = None # 将index的name取消
df.reset_index(inplace=True)
df.drop(df.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
df['index'] = date_list
df.set_index(['index'], inplace=True)
先看传统汽车整体趋势:
dta = np.array(df['传统汽车销量'], dtype=np.float)
# 生成时间序列并画图
dta = pd.Series(dta)
dta.index = df.index
# 趋势
dta.plot(figsize=(12, 8), title='Monthly Total Traditional Car')
有明显的递增趋势,可以判断是非平稳的,再来看看是否有季节性:
decomposition = seasonal_decompose(df['传统汽车销量'], freq=12)
fig = plt.figure()
fig = decomposition.plot()
fig.set_size_inches(15, 8)
可以看到有明显季节性波动,需要将数据平稳化,这里我用简单的二阶差分进行(这里可以配合季节性差分进行测试(shift(12) ),最终选择差分方式)
fig = plt.figure(figsize=(12, 8))
ax2 = fig.add_subplot(111)
diff2 = dta.diff(2)
diff2.plot(ax=ax2)
可以看到效果还可以。基础上还可以进行根检验:
sm.tsa.stattools.adfuller(diff2[2:]
如何确定差分阶数和常数项:
-
假如时间序列在很高的lag(10以上)上有正的ACF,则需要很高阶的差分
-
假如lag-1的ACF是0或负数或者非常小,则不需要很高的差分,假如lag-1的ACF是-0.5或更小,序列可能overdifferenced。BEWARE OF OVERDIFFERENCING
-
最优的差分阶数一般在最优阶数下标准差最小(但并不是总数如此)
-
模型不差分意味着原先序列是平稳的;1阶差分意味着原先序列有个固定的平均趋势;二阶差分意味着原先序列有个随时间变化的趋势
-
模型没有差分一般都有常数项;有两阶差分一般没常数项;假如1阶差分模型非零的平均趋势,则有常数项
如何确定AR和MA的阶数:
-
假如PACF显示截尾或者lag-1的ACF是正的(此时序列仍然有点underdifferenced),则需要考虑AR项;PACF的截尾项表明AR的阶数
-
假如ACF显示截尾或者lag-1的ACF是负的(此时序列有点overdifferenced),则需要加MA项,ACF的截尾项表明AR的阶数
-
AR和MA可以相互抵消对方的影响,所以假如用AR-MA模型去拟合数据,仍然需要考虑加些AR或MA项。尤其在原先模型需要超过10次的迭代去converge。BEWARE OF USING MULTIPLE AR TERMS AND MULTIPLE MA TERMS IN THE SAME MODEL.
-
假如在AR部分有个单位根(AR系数和大约为1),此时应该减少一项AR增加一次差分
-
假如在MA部分有个单位根(MA系数和大约为1),此时应该减少一项AR减少一次差分
-
假如长期预测出现不稳定,则可能AR、MA系数有单位根
如何确定季节性部分:
-
假如序列有显著是季节性模式,则需要用季节性差分,但是不要使用两次季节性差分或总过超过两次差分(季节性和非季节性)
-
假如差分序列在滞后s处有正的ACF,s是季节的长度,则需要加入SAR项;假如差分序列在滞后s处有负的ACF,则需要加入SMA项,如果使用了季节性差异,则后一种情况很可能发生,如果数据具有稳定和合乎逻辑的季节性模式。如果没有使用季节性差异,前者很可能会发生,只有当季节性模式不稳定时才适用。应该尽量避免在同一模型中使用多于一个或两个季节性参数(SAR + SMA),因为这可能导致过度拟合数据和/或估算中的问题。
接下来寻找最优p,q值组合: arma_mod70 = sm.tsa.ARMA(dta, (7, 0)).fit() print(arma_mod70.aic, arma_mod70.bic, arma_mod70.hqic) arma_mod30 = sm.tsa.ARMA(dta, (0, 1)).fit() print(arma_mod30.aic, arma_mod30.bic, arma_mod30.hqic) arma_mod80 = sm.tsa.ARMA(dta, (8, 0)).fit() print(arma_mod80.aic, arma_mod80.bic, arma_mod80.hqic) 结果如下 754.1050637800771 773.6745492091378 761.8264803250283 835.8762241876609 842.3993859973478 838.4500297026447 754.4743430156554 776.2182157146118 763.0536947322679 可以看出ARMA(8,0) 和ARMA(7,0) 是差不多的 ,这里选择两个对结果没有太大影响。 最后可以进行预测了
# 预测
predict_dta = arma_mod80.predict('2019', '2021', dynamic=True)
print(predict_dta)
fig, ax = plt.subplots(figsize=(12, 8))
ax = dta.ix['2000':].plot(ax=ax)
fig = arma_mod80.plot_predict('2019', '2021', dynamic=True, ax=ax, plot_insample=False)
预测结果
2019-01-01 713.995946
2019-04-01 621.508451
2019-07-01 595.797886
2019-10-01 637.026010
2020-01-01 647.507366
2020-04-01 620.106670
2020-07-01 594.113071
2020-10-01 597.800788
2021-01-01 613.222166