1. 程式人生 > 實用技巧 >時間序列分析

時間序列分析

https://www.cnblogs.com/rix-yb/p/9919787.html

時間序列分析

一、 概念

時間序列(Time Series)

時間序列是指同一統計指標的數值按其發生的時間先後順序排列而成的數列(是均勻時間間隔上的觀測值序列)。

時間序列分析的主要目的是根據已有的歷史資料對未來進行預測。

時間序列分析主要包括的內容有:趨勢分析、序列分解、序列預測。

時間序列分解(Time-Series Decomposition)

時間序列按照季節性來分類,分為季節性時間序列和非季節性時間序列。

時間序列的構成要素:

  • 長期趨勢 T:現象在較長時期內受某種根本性因素作用而形成的總的變動趨勢
  • 季節變動 S:現象在一年內隨著季節的變化而發生的有規律的週期性變動
  • 迴圈趨勢 C:現象以若干年為週期呈現出的波浪起伏形態的有規律的變動
  • 不規則變動 I:是一種無規律可循的變動,包括嚴格的隨機變動和不規則的突發性影響很大的變動兩種型別

二、 非季節性時間序列

移動平均(MA,Moving Average)

移動平均是一種簡單平滑技術,它通過在時間序列上逐項退役取一定項數的均值,來表現指標的長期變化和發展趨勢

1、 簡單移動平均(SMA)

簡單移動平均將時間序列上前n個數值做簡單的算術平均。

SMAn = ( x1 + x2 + …… + xn)/ n

2、 加權移動平均(WMA)

加權移動平均,在基於簡單移動平均的基礎上,對時間序列上前n期的每一期數值賦予相應的權重,即加權平均的結果

基本思想:提升近期的資料、減弱遠期資料對當前預測值的影響,使預測值更貼近最近的變化趨勢。

WMAn = w1x1 + w2x2 + …… + wnxn

3、 非季節性時間序列的分解

將非季節性時間序列分解為 趨勢 和 不規則波動 兩個部分。

#匯入資料並繪製圖形,得到如下的圖形

簡單移動平均法分解

#設定移動平均視窗為5,檢視平滑後的曲線

Y = y.rolling(5).mean()
plt.plot(x, y, 'k', x, Y, 'g')
#移動平均後的曲線平滑向上

#求出不規則波動

#求出不規則變動
y_ = y - Y 
plt.plot(x, y, 'b', x, Y, 'g', x, y_, 'r')
#不規則變動在0上下波動

加權移動平均法分解

#設定視窗大小及權重,得到圖形

w = 3
ww = np.arange(1, w+1)
ww = ww / sum(ww)

def wma(window):
    return np.sum(window * ww)

Y = y.rolling(w).aggregate(wma)
plt.plot(x, y, 'k', x, Y, 'g')

#調整視窗為5後再次繪圖

#趨勢更加明顯,然後求出不規則波動




三、 季節性時間序列

在一個時間序列中,若經過n個時間間隔後呈現出相似性,該序列具有以n為週期的季節性特性。

季節性時間序列的分解

將季節性時間序列分解為 趨勢 、週期性 和 不規則波動 三個部分。

tips:需要將時間列轉換成索引列,方便計算

#將時間序列做為索引
dateparse = lambda dates: pd.datetime.strptime(dates, '%Y%m%d')

data = pd.read_csv('filepath',
                   parse_dates=['時間'],
                   date_parser=dateparse,
                   index_col='時間'
                  )

#設定時間序列週期,並使用statsmodels.api包中的seasonal_decompose方法得到分解圖形

import statsmodels.api as sm 

rd = sm.tsa.seasonal_decompose(data['總銷量'].values, freq=7)

resplot = rd.plot()

#得到如下的分解圖形——原始資料、趨勢資料、週期性資料、隨機變數

#再通過如下程式碼,得到分解部分的資料輸出

#得到趨勢、週期性、隨機變數的資料輸出
rd.trend
rd.seasonal
rd.resid

四、 序列預測

1、概念

預測(forecast)

對尚未發生或目前還不明確的事物進行預先的估計和推測,是在現時對事物將要發生的結果進行探討和研究,簡單的說就是指從已知事件預測未知事件。

時間序列預測(Time Series Forecasting

通過分析時間序列,根據時間序列所反映出來的發展過程、方向和趨勢,進行類推或延申,藉以預測下一段時間或以後若干時間段內可能達到的水平。

平穩型時間序列(Stationary Time Series)

平穩時間序列,其統計特徵不隨時間變化二變換,一般採用均值、方差或者協方差來作為統計特徵。

差分(Integrated)

差分是一種讓時間序列資料平穩的常用手段,異界差分的公式為:。n階差分,是在n-1階差分的基礎上,按照一階差分的公式進行計算。

常用的時間序列預測模型:

AR(p)模型(Autoregressive Model):自迴歸模型描述的是當前值與歷史值之間的關係

MA(q)模型(Moving Average Model):移動平均模型描述的是自迴歸部分的誤差累計

ARMA模型:所謂ARMA模型,是指將非平穩時間序列轉化為平穩時間序列,然後將因變數僅對它的滯後值以及隨機誤差項的現值和滯後值進行迴歸所建立的模型。

python實現ARMA模型的預測

#資料索引列處理
dateparse = lambda dates: pd.datetime.strptime(dates, '%Y%m%d')
data = pd.read_csv(r'filepath',
                   parse_dates=['date'],
                   date_parser=dateparse,
                   index_col='date',
                   encoding='utf-8',
                   engine='python')


#繪圖觀察時間序列是否平穩
plt.figure(figsize=(10, 6))
plt.plot(data, 'r', label='Raw')
plt.legend(loc=0)

#觀察到序列隨時間呈上升趨勢,非平穩




#時間序列平穩性檢驗模組

#時間序列平穩性檢驗模組 
def tagADF(t):
    result = pd.DataFrame(index=[
            "Test Statistic Value", "p-value", "Lags Used", 
            "Number of Observations Used", 
            "Critical Value(1%)", "Critical Value(5%)", "Critical Value(10%)"
        ], columns=['value'])
    
    result['value']['Test Statistic Value'] = t[0]
    result['value']['p-value'] = t[1]
    result['value']['Lags Used'] = t[2]
    result['value']['Number of Observations Used'] = t[3]
    result['value']['Critical Value(1%)'] = t[4]['1%']
    result['value']['Critical Value(5%)'] = t[4]['5%']
    result['value']['Critical Value(10%)'] = t[4]['10%']
    return result
#檢測方法
adf_Data = ts.adfuller(data.iloc[:,0])
#基於時間序列不平穩的假設而進行平穩性檢驗
tagADF(adf_Data)  
#得到如下結果,P值0.69,表示69%的可能性該序列非平穩

#檢視檢驗結果中的p值可以判斷序列是否平穩,若不平穩則需要進行差分

#一階差分處理
diff = data.diff(1).dropna()
#對一階差分後的資料進行繪圖
plt.figure(figsize=(10, 6))
plt.plot(diff, 'r', label='Diff')
plt.legend(loc=0)
#差分處理後的圖形如下,勉強分辨出差分後的序列沿0上下波動
#對差分後的資料再次進行平穩性檢驗
adfdiff = ts.adfuller(diff.iloc[:,0])
tagADF(adfdiff)
#p值非常小,認為該差分後的序列平穩

#若差分後的序列平穩,則進行ARMR模型中p值和q值的確定

#通過傳入限定的最大值,得到最佳的p值和q值(耗時較長)
ic = sm.tsa.arma_order_select_ic(diff, max_ar=20, max_ma=20, ic='aic')

#構建模型

#得到最佳p值和q值
order = (15, 9)
#ARMA模型建模和訓練
ARMAmodel = sm.tsa.ARMA(diff, order).fit()
#得到模型評分
delta = ARMAmodel.fittedvalues - diff.iloc[:0]
score = 1- delta.var() / diff.var()

#繪圖得到擬合曲線
plt.figure(figsize=(10, 6))
plt.plot(diff, 'r', label='Raw')
plt.plot(ARMAmodel.fittedvalues, 'g', label='ARMAmodel')
plt.legend()
#觀察圖形,模型曲線與一階差分曲線擬合性較好

#資料預測

#輸入起始時間和結束時間,進行資料預測(差分後的值,需要進行還原)
p = ARMAmodel.predict(start='2016-03-31', end='2016-04-10')
#得到如下結果




#將預測得到的差分值進行還原

#將差分值進行還原
def revert(diffValues, *lastValue):
    for i in range(len(lastValue)):
        result = []
        lv = lastValue[i]
        for dv in diffValues:
            lv = dv + lv
            result.append(lv)
        diffValues = result
    return diffValues
#需要輸入序列的最後一個值   
r = revert(p, 10395)
#得到還原後的結果