Python的科学计算和数据挖掘相关库中,pandas和statsmodels都提供了时间序列相关分析功能,本示例使用的是statsmodels做时间序列预测应用。有关时间序列算法的选择,实际场景中最常用的是ARIMA或ARMA了,因此本示例将使用ARIMA/ARMA来做时间序列分析。
对于这两种时间序列方法而言,应用的难点是如何根据不同的场景判断参数值(即p、d、q)。本示例将设置判断阀值,通过自动化的程序方式来完成自动的ARIMA/ARMA的参数(p、d、q)选择以及模型训练,降低时间序列算法应用的难度。
示例中模拟的是针对具有时间序列特征的数据集做未来时间序列的预测,数据源文件time_series.txt可以从《Python数据分析与数据化运营》的"附件-chapter4”中找到,该附件可以在可从http://www.dataivy.cn/book/python_book.zip或https://pan.baidu.com/s/1kUUBWNX下载。
第一部分导入库
statsmodels库里面的plot_acf、plot_pacf用于acf和pacf图形检验分析,adfuller、acorr_ljungbox用于adf检验和随机性检验,ARMA库做时间序列分析,matplotlib和prettytable做图形和表格格式化输出。
#?导入库
import?pandas?as?pd??#?pandas库
import?numpy?as?np??#?numpy库
from?statsmodels.graphics.tsaplots?import?plot_acf,?plot_pacf??#?acf和pacf展示库
from?statsmodels.tsa.stattools?import?adfuller??#?adf检验库
from?statsmodels.stats.diagnostic?import?acorr_ljungbox??#?随机性检验库
from?statsmodels.tsa.arima_model?import?ARMA??#?ARMA库
import?matplotlib.pyplot?as?plt??#?matplotlib图形展示库
import?prettytable??#?导入表格库
提示 ARIMA相对于ARMA多了一步差分的过程,但是由于statsmodels中的ARIMA对差分的支持不太好,最多只能多2阶差分,其实用性会大打折扣(其实2阶差分已经可以满足90%以上的场景了)。所以,在实际应用中,我们会手动做数据平稳性处理,然后将平稳数据传给ARMA模型做训练,完成ARIMA的时间序列分析。
第二部分定义一个名为pre_table的函数
该函数用来展示格式化表格数据,方便每次展示时调用而无需重复编写代码。
该函数的输入有2个参数:
table_name:表格名称,字符串列表;
table_rows:表格内容,嵌套列表,考虑到在添加内容时,可能会有批量添加的模式,因此批量添加的数据记录行需要转换为嵌套列表的形式,例如[[1,2,3,4],[2,2,3,4]]为要添加的两条数据记录;即使只有一条数据记录,也要写成嵌套列表的形式,例如[[1,2,3,4]]。
返回一个包含内容的可打印对象。
#?多次用到的表格
def?pre_table(table_name,?table_rows):
”’
:param?table_name:?表格名称,字符串列表
:param?table_rows:?表格内容,嵌套列表
:return:?展示表格对象
”’
table?=?prettytable.PrettyTable()??#?创建表格实例
table.field_names?=?table_name??#?定义表格列名
for?i?in?table_rows:??#?循环读多条数据
table.add_row(i)??#?增加数据
return?table
函数功能中,先通过prettytable.PrettyTable创建表格对象实例,然后通过实例的field_names方法增加表格名称,通过一个for循环将table_rows中的多个嵌套表格内容读出,并使用表格实例的add_row方法增加行数据。
第三部分定义一个名为get_best_log的函数
该函数用于数据平稳处理。该函数的输入参数有5个:
ts:时间序列数据,Series类型
max_log:最大log处理的次数,默认值为5,int型
rule1:rule1规则布尔值,默认值为True,布尔型
rule2:rule2规则布尔值,默认值为True,布尔型
返回:达到平稳处理的最佳log处理次数和处理后的时间序列
#?数据平稳处理
def?get_best_log(ts,?max_log=5,?rule1=True,?rule2=True):
”’
:param?ts:?时间序列数据,Series类型
:param?max_log:?最大log处理的次数,int型
:param?rule1:?rule1规则布尔值,布尔型
:param?rule2:?rule2规则布尔值,布尔型
:return:?达到平稳处理的最佳次数值和处理后的时间序列
”’
if?rule1?and?rule2:??#?如果两个规则同时满足
return?0,?ts??#?直接返回0和原始时间序列数据
else:??#?只要有一个规则不满足
for?i?in?range(1,?max_log):??#?循环做log处理
ts?=?np.log(ts)??#?log处理
lbvalue,?pvalue1?=?acorr_ljungbox(ts,?lags=1)??#?白噪声检验结果
adf,?pvalue2,?usedlag,?nobs,?critical_values,?icbest?=?adfuller(ts)??#?ADF检验
rule_1?=?(adf?<?critical_values["1%’]?and?adf?<?critical_values["5%’]?and?adf?<?critical_values["10%’]?and?pvalue1?<?0.01)??#?稳定性检验
rule_2?=?(pvalue2?<?0.05)??#?白噪声检验
rule_3?=?(i?<?5)
if?rule_1?and?rule_2?and?rule_3:??#?如果同时满足条件
print?("The?best?log?n?is:?{0}’.format(i))??#?打印输出最佳次数
return?i,?ts??#?返回最佳次数和处理后的时间序列
该函数功能中,先通过rule1 和 rule2条件判断输入的两个规则是否同时满足,如果同时满足则说明该时间序列是平稳的,无需做任何平稳性处理;否则使用对数方法(numpy.log)做平稳性处理:
通过for循环按照指定的最大处理次数做循环处理,一般情况下做2次log处理就能满足90%的时间序列平稳性。
每次处理后使用acorr_ljungbox做白噪声检验、使用adfuller方法做ADF检验,如果二者检验的结果能够符合两个规则的阀值设定并且i的值在5以内,那么返回平稳处理的次数以及处理后的时间序列;否则终止程序。平稳处理的次数用于后期数据的还原,处理后的时间序列用于ARMA模型中的时间序列的输入数据集。
相关知识点:时间序列数据的平稳性
平稳性是做时间序列分析的前提条件,所谓平稳通俗理解就是数据没有随着时间呈现明显的趋势和规律,例如剧烈波动、递增、递减等,而是相对均匀且随机的分布在均值附近。在ARIMA模型中的I就是对数据做差分以实现数据的平稳,而ARIMA关键参数p、d、q中的d即时间序列成为平稳时所做的差分次数。
如何判断时间序列数据是否需要平稳性处理?一般有两种方法:
观察法:通过输出时间序列图发现数据是否平稳。本示例中的adf_val函数便有含有该方法。
自相关和偏相关法:通过观察自相关和偏相关的系数分析数据是否平稳。
ADF检验:通过ADF检验得到的显著性水平分析数据是否平稳。本示例中的adf_val函数便有含有该方法。
实现数据的平稳有以下几种方法:
对数法:对数处理可以减小数据的波动,使其线性规律更加明显。但需要注意的是对数处理只能针对时间序列的值大于0的数据集。
差分法:一般来说,非纯随机的时间序列经一阶差分或者二阶差分之后就会变得平稳(statsmodels的ARIMA模型自动支持数据差分,但最大为2阶差分)。
平滑法:根据平滑技术的不同,可分为移动平均法和指数平均法,这两个都是最基本的时间序列方法。