时序数据的分析

时序数据的分析最近工作中遇到了时序预测问题 查询了部分博客找到部分特征工程的处理过程 感觉还可以分享一下 参考地址 https www cnblogs com bradleon p 6832867 html 原始数据的检测 波动 平稳性 周期 方差等 和时间序列的预测代码参考 https blog csdn net 33472765 article details 85226361 时间序

最近工作中遇到了时序预测问题,查询了部分博客找到部分特征工程的处理过程,感觉还可以分享一下:

参考地址:https://www.cnblogs.com/bradleon/p/6832867.html

原始数据的检测(波动,平稳性,周期,方差等)和时间序列的预测代码参考:https://blog.csdn.net/_/article/details/

时间序列问题的特征工程(四个方向)参考:https://yq.aliyun.com/ziliao/


在阅读本文之前 ,推荐先阅读:http://www.cnblogs.com/bradleon/p/6827109.html

导读

本文主要分为四个部分:

  1. 用pandas处理时序数据
  2. 怎样检查时序数据的稳定性
  3. 怎样让时序数据具有稳定性
  4. 时序数据的预测

1. 用pandas导入和处理时序数据

第一步:导入常用的库

import pandas as pd import numpy as np import matplotlib.pylab as plt from matplotlib.pylab import rcParams #rcParams设定好画布的大小 rcParams['figure.figsize'] = 15, 6
data = pd.read_csv(path+"AirPassengers.csv") print data.head() print '\n Data types:' print data.dtypes
dateparse = lambda dates: pd.datetime.strptime(dates, '%Y-%m') #---其中parse_dates 表明选择数据中的哪个column作为date-time信息, #---index_col 告诉pandas以哪个column作为 index #--- date_parser 使用一个function(本文用lambda表达式代替),使一个string转换为一个datetime变量 data = pd.read_csv('AirPassengers.csv', parse_dates=['Month'], index_col='Month',date_parser=dateparse) print data.head() print data.index

2.怎样检查时序数据的稳定性(Stationarity)

因为ARIMA模型要求数据是稳定的,所以这一步至关重要。

1. 判断数据是稳定的常基于对于时间是常量的几个统计量:

  1. 常量的均值
  2. 常量的方差
  3. 与时间独立的自协方差

用图像说明如下:

  1. 均值
    filelist
    X是时序数据的值,t是时间。可以看到左图,数据的均值对于时间轴来说是常量,即数据的均值不是时间的函数,所有它是稳定的;右图随着时间的推移,数据的值整体趋势是增加的,所有均值是时间的函数,数据具有趋势,所以是非稳定的。




  2. 方差
    filelist
    可以看到左图,数据的方差对于时间是常量,即数据的值域围绕着均值上下波动的振幅是固定的,所以左图数据是稳定的。而右图,数据的振幅在不同时间点不同,所以方差对于时间不是独立的,数据是非稳定的。但是左、右图的均值是一致的。




  3. 自协方差
    filelist
    一个时序数据的自协方差,就是它在不同两个时刻i,j的值的协方差。可以看到左图的自协方差于时间无关;而右图,随着时间的不同,数据的波动频率明显不同,导致它i,j取值不同,就会得到不同的协方差,因此是非稳定的。虽然右图在均值和方差上都是与时间无关的,但仍是非稳定数据。




2. python判断时序数据稳定性

  1. Dickey-Fuller Test — 这个比较复杂,大致意思就是在一定置信水平下,对于时序数据假设 Null hypothesis: 非稳定。
    if 通过检验值(statistic)< 临界值(critical value),则拒绝null hypothesis,即数据是稳定的;反之则是非稳定的。

from statsmodels.tsa.stattools import adfuller def test_stationarity(timeseries): #这里以一年为一个窗口,每一个时间t的值由它前面12个月(包括自己)的均值代替,标准差同理。 rolmean = pd.rolling_mean(timeseries,window=12) rolstd = pd.rolling_std(timeseries, window=12) #plot rolling statistics: fig = plt.figure() fig.add_subplot() orig = plt.plot(timeseries, color = 'blue',label='Original') mean = plt.plot(rolmean , color = 'red',label = 'rolling mean') std = plt.plot(rolstd, color = 'black', label= 'Rolling standard deviation') plt.legend(loc = 'best') plt.title('Rolling Mean & Standard Deviation') plt.show(block=False) #Dickey-Fuller test: print 'Results of Dickey-Fuller Test:' dftest = adfuller(timeseries,autolag = 'AIC') #dftest的输出前一项依次为检测值,p值,滞后数,使用的观测数,各个置信度下的临界值 dfoutput = pd.Series(dftest[0:4],index = ['Test Statistic','p-value','#Lags Used','Number of Observations Used']) for key,value in dftest[4].items(): dfoutput['Critical value (%s)' %key] = value print dfoutput ts = data['#Passengers'] test_stationarity(ts)

时序数据的分析
可以看到,数据的rolling均值/标准差具有越来越大的趋势,是不稳定的。
且DF-test可以明确的指出,在任何置信度下,数据都不是稳定的。




3. 让时序数据变成稳定的方法

让数据变得不稳定的原因主要有俩:

  1. 趋势(trend)-数据随着时间变化。比如说升高或者降低。
  2. 季节性(seasonality)-数据在特定的时间段内变动。比如说节假日,或者活动导致数据的异常。

由于原数据值域范围比较大,为了缩小值域,同时保留其他信息,常用的方法是对数化,取log。

ts_log = np.log(ts)
  1. 检测和去除趋势
    通常有三种方法:


    • 聚合 : 将时间轴缩短,以一段时间内星期/月/年的均值作为数据值。使不同时间段内的值差距缩小。
    • 平滑: 以一个滑动窗口内的均值代替原来的值,为了使值之间的差距缩小
    • 多项式过滤:用一个回归模型来拟合现有数据,使得数据更平滑。

本文主要使用平滑方法

Moving Average–移动平均

moving_avg = pd.rolling_mean(ts_log,12) plt.plot(ts_log ,color = 'blue') plt.plot(moving_avg, color='red')

时序数据的分析
可以看出moving_average要比原值平滑许多。

然后作差:

ts_log_moving_avg_diff = ts_log-moving_avg ts_log_moving_avg_diff.dropna(inplace = True) test_stationarity(ts_log_moving_avg_diff)

时序数据的分析
时序数据的分析
可以看到,做了处理之后的数据基本上没有了随时间变化的趋势,DFtest的结果告诉我们在95%的置信度下,数据是稳定的。




上面的方法是将所有的时间平等看待,而在许多情况下,可以认为越近的时刻越重要。所以引入指数加权移动平均– Exponentially-weighted moving average.(pandas中通过ewma()函数提供了此功能。)

# halflife的值决定了衰减因子alpha: alpha = 1 - exp(log(0.5) / halflife) expweighted_avg = pd.ewma(ts_log,halflife=12) ts_log_ewma_diff = ts_log - expweighted_avg test_stationarity(ts_log_ewma_diff)

时序数据的分析
时序数据的分析
可以看到相比普通的Moving Average,新的数据平均标准差更小了。而且DFtest可以得到结论:数据在99%的置信度上是稳定的。




  1. 检测和去除季节性
    有两种方法:


    • 1 差分化: 以特定滞后数目的时刻的值的作差
    • 2 分解: 对趋势和季节性分别建模在移除它们

Differencing–差分

ts_log_diff = ts_log - ts_log.shift() ts_log_diff.dropna(inplace=True) test_stationarity(ts_log_diff)

时序数据的分析
如图,可以看出相比MA方法,Differencing方法处理后的数据的均值和方差的在时间轴上的振幅明显缩小了。DFtest的结论是在90%的置信度下,数据是稳定的。

3.Decomposing-分解

#分解(decomposing) 可以用来把时序数据中的趋势和周期性数据都分离出来: from statsmodels.tsa.seasonal import seasonal_decompose def decompose(timeseries): # 返回包含三个部分 trend(趋势部分) , seasonal(季节性部分) 和residual (残留部分) decomposition = seasonal_decompose(timeseries) trend = decomposition.trend seasonal = decomposition.seasonal residual = decomposition.resid plt.subplot(411) plt.plot(ts_log, label='Original') plt.legend(loc='best') plt.subplot(412) plt.plot(trend, label='Trend') plt.legend(loc='best') plt.subplot(413) plt.plot(seasonal,label='Seasonality') plt.legend(loc='best') plt.subplot(414) plt.plot(residual, label='Residuals') plt.legend(loc='best') plt.tight_layout() return trend , seasonal, residual

时序数据的分析
如图可以明显的看到,将original数据 拆分成了三份。Trend数据具有明显的趋势性,Seasonality数据具有明显的周期性,Residuals是剩余的部分,可以认为是去除了趋势和季节性数据之后,稳定的数据,是我们所需要的。

#消除了trend 和seasonal之后,只对residual部分作为想要的时序数据进行处理 trend , seasonal, residual = decompose(ts_log) residual.dropna(inplace=True) test_stationarity(residual)

时序数据的分析
时序数据的分析
如图所示,数据的均值和方差趋于常数,几乎无波动(看上去比之前的陡峭,但是要注意他的值域只有[-0.05,0.05]之间),所以直观上可以认为是稳定的数据。另外DFtest的结果显示,Statistic值原小于1%时的Critical value,所以在99%的置信度下,数据是稳定的。




4. 对时序数据进行预测

step1: 通过ACF,PACF进行ARIMA(p,d,q)的p,q参数估计

yt=Yt−Yt−1

作为输入。

先画出ACF,PACF的图像,代码如下:

#ACF and PACF plots: from statsmodels.tsa.stattools import acf, pacf lag_acf = acf(ts_log_diff, nlags=20) lag_pacf = pacf(ts_log_diff, nlags=20, method='ols') #Plot ACF: plt.subplot(121) plt.plot(lag_acf) plt.axhline(y=0,linestyle='--',color='gray') plt.axhline(y=-1.96/np.sqrt(len(ts_log_diff)),linestyle='--',color='gray') plt.axhline(y=1.96/np.sqrt(len(ts_log_diff)),linestyle='--',color='gray') plt.title('Autocorrelation Function') #Plot PACF: plt.subplot(122) plt.plot(lag_pacf) plt.axhline(y=0,linestyle='--',color='gray') plt.axhline(y=-1.96/np.sqrt(len(ts_log_diff)),linestyle='--',color='gray') plt.axhline(y=1.96/np.sqrt(len(ts_log_diff)),linestyle='--',color='gray') plt.title('Partial Autocorrelation Function') plt.tight_layout()

时序数据的分析
图中,上下两条灰线之间是置信区间,p的值就是ACF第一次穿过上置信区间时的横轴值。q的值就是PACF第一次穿过上置信区间的横轴值。所以从图中可以得到p=2,q=2。

from statsmodels.tsa.arima_model import ARIMA model = ARIMA(ts_log, order=(2, 1, 0)) results_AR = model.fit(disp=-1) plt.plot(ts_log_diff) plt.plot(results_AR.fittedvalues, color='red') plt.title('RSS: %.4f'% sum((results_AR.fittedvalues-ts_log_diff)2))

时序数据的分析
图中,蓝线是输入值,红线是模型的拟合值,RSS的累计平方误差。

模型2:MA模型(ARIMA(0,1,2))

model = ARIMA(ts_log, order=(0, 1, 2)) results_MA = model.fit(disp=-1) plt.plot(ts_log_diff) plt.plot(results_MA.fittedvalues, color='red') plt.title('RSS: %.4f'% sum((results_MA.fittedvalues-ts_log_diff)2))

时序数据的分析

模型3:ARIMA模型(ARIMA(2,1,2))

model = ARIMA(ts_log, order=(2, 1, 2)) results_ARIMA = model.fit(disp=-1) plt.plot(ts_log_diff) plt.plot(results_ARIMA.fittedvalues, color='red') plt.title('RSS: %.4f'% sum((results_ARIMA.fittedvalues-ts_log_diff)2))

时序数据的分析
由RSS,可知模型3–ARIMA(2,1,2)的拟合度最好,所以我们确定了最终的预测模型。

 #ARIMA拟合的其实是一阶差分ts_log_diff,predictions_ARIMA_diff[i]是第i个月与i-1个月的ts_log的差值。 #由于差分化有一阶滞后,所以第一个月的数据是空的, predictions_ARIMA_diff = pd.Series(results_ARIMA.fittedvalues, copy=True) print predictions_ARIMA_diff.head() #累加现有的diff,得到每个值与第一个月的差分(同log底的情况下)。 #即predictions_ARIMA_diff_cumsum[i] 是第i个月与第1个月的ts_log的差值。 predictions_ARIMA_diff_cumsum = predictions_ARIMA_diff.cumsum() #先ts_log_diff => ts_log=>ts_log => ts #先以ts_log的第一个值作为基数,复制给所有值,然后每个时刻的值累加与第一个月对应的差值(这样就解决了,第一个月diff数据为空的问题了) #然后得到了predictions_ARIMA_log => predictions_ARIMA predictions_ARIMA_log = pd.Series(ts_log.ix[0], index=ts_log.index) predictions_ARIMA_log = predictions_ARIMA_log.add(predictions_ARIMA_diff_cumsum,fill_value=0) predictions_ARIMA = np.exp(predictions_ARIMA_log) plt.figure() plt.plot(ts) plt.plot(predictions_ARIMA) plt.title('RMSE: %.4f'% np.sqrt(sum((predictions_ARIMA-ts)2)/len(ts)))

时序数据的分析

5.总结

  1. 怎样让时序数据稳定化。对应步骤(2)
  2. 使用ARIMA模型进行时序数据预测。对应步骤(3,4)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/200144.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月20日 上午11:26
下一篇 2026年3月20日 上午11:27


相关推荐

  • dnf自己搭建服务器_dnf搭建教程

    dnf自己搭建服务器_dnf搭建教程DNF游戏私服搭建过程准备资源:1.黑岩客户端2.服务器启动所需资源3.1核2G服务器一台(版本centos5.8)(记得开放全部端口)服务端配置:步骤一:切换源为163的源:wget-O/etc/yum.repos.d/CentOS-Base.repohttp://mirrors.163.com//.help/CentOS5-Base-163.repo上传资源到服务器的根目录cd/上传文件步骤二:安装glibc.i386,xulrunner.i386,libXt

    2022年10月5日
    4
  • 电信网通全国DNS 列表「建议收藏」

    电信网通全国DNS列表电信DNS列表(按拼音排序,共32条)电信A安徽202.102.192.68202.102.199.68电信A澳门202.175.3.8202.175.3.3电信B北京202.96.199.133202.96.0.133202.106.0.20202.106.148.1电信C重庆61.128…

    2022年4月16日
    133
  • 分享一个不错的数据分析实战案例【全程附图】EXCEL

    分享一个不错的数据分析实战案例【全程附图】EXCEL利用最近一次的营销活动的信息,分析什么对推销结果的影响最大,如何确定银行定期产品推销中最具价值的客户。

    2022年6月1日
    40
  • linux磁盘空间查看与清理

    linux磁盘空间查看与清理大早上 收到用户反馈 服务启动不了 明明昨天还好好的 今天这是怎么了呢 水土不服 经过分析排查发下 磁盘空间使用率已经是 100 了 磁盘满了 当然起不来了 下面记录一下 查看内容记录 1 查看 opt 当前可用磁盘空间 cd optdf h 发现已用 100 了 2 查看占用空间比较大的文件 du hmax depth 1 查找之后发下是 log 文件过大 发现问题 找到问题 那就不要客气了 下一步解决问题 3 rm frlog 清理完毕 结束 注意 如果

    2026年3月18日
    2
  • 小树剪发网1114_aow把抓

    小树剪发网1114_aow把抓乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过 50 个长度单位。然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。请你设计一个程序,帮助乔治计算木棒的可能最小长度。每一节木棍的长度都用大于零的整数表示。输入格式输入包含多组数据,每组数据包括两行。第一行是一个不超过 64 的整数,表示砍断之后共有多少节木棍。第二行是截断以后,所得到的各节木棍的长度。在最后一组数据之后,是一个零。输出格式为每组数据,分别输出原始木棒的可能最小长度

    2022年8月8日
    9
  • claude code使用qwen3-coder模型详细教程

    claude code使用qwen3-coder模型详细教程

    2026年3月16日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号