時間序列分析python
1、 概念api
時間序列(Time Series)app
時間序列是指同一統計指標的數值按其發生的時間前後順序排列而成的數列(是均勻時間間隔上的觀測值序列)。spa
時間序列分析的主要目的是根據已有的歷史數據對將來進行預測。3d
時間序列分析主要包括的內容有:趨勢分析、序列分解、序列預測。code
時間序列分解(Time-Series Decomposition)blog
時間序列按照季節性來分類,分爲季節性時間序列和非季節性時間序列。索引
時間序列的構成要素:事件
2、 非季節性時間序列ip
移動平均(MA,Moving Average)
移動平均是一種簡單平滑技術,它經過在時間序列上逐項退役取必定項數的均值,來表現指標的長期變化和發展趨勢
一、 簡單移動平均(SMA)
簡單移動平均將時間序列上前n個數值作簡單的算術平均。
SMAn = ( x1 + x2 + …… + xn)/ n
二、 加權移動平均(WMA)
加權移動平均,在基於簡單移動平均的基礎上,對時間序列上前n期的每一期數值賦予相應的權重,即加權平均的結果
基本思想:提高近期的數據、減弱遠期數據對當前預測值的影響,使預測值更貼近最近的變化趨勢。
WMAn = w1x1 + w2x2 + …… + wnxn
三、 非季節性時間序列的分解
將非季節性時間序列分解爲 趨勢 和 不規則波動 兩個部分。
#導入數據並繪製圖形,獲得以下的圖形
簡單移動平均法分解
#設置移動平均窗口爲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後再次繪圖
#趨勢更加明顯,而後求出不規則波動
3、 季節性時間序列
在一個時間序列中,若通過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
4、 序列預測
一、概念
預測(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)
#獲得還原後的結果