時間序列是隨時間變化的序列,總體可分為 平穩 與 非平穩序列;
平穩序列
平穩序列即經由 樣本時間序列 得到的擬合曲線在未來一段時間內仍能沿着現有形態發展下去;
數學描述如下:
均值和方差 不 隨時間 t 變化而變化;
協方差 cov(xt,xt+k) 只與 周期(或者說時間間隔) K 有關,與時間 t 無關;
平穩序列又分為嚴平穩和弱平穩
嚴平穩:序列值的分布不隨時間變化而變化;
如 白噪聲序列,無論怎么取,均值為 0,方差為 S^2;
既然沒有任何變化,就沒有研究的價值了;
弱平穩:期望與相關系數(依賴性)不變,也就是說 當前序列值 與 它前些時刻的值 有關,存在依賴性;
有依賴才有研究價值;
小結
平穩的時間序列才有研究價值;
時間序列分析針對的是 弱平穩序列;
差分變換
通常情況下,非平穩序列可通過 差分變換 轉化為平穩序列
DataFrame.diff(periods=1, axis=0)
periods:差分步長,xt-xt-periods;
axis:維度;
fig, axs = plt.subplots(4, 1) ##### 非平穩序列 np.random.seed(12345) ut = np.random.randint(-30, 30, size=(100)) xt = np.cumsum(ut) + 500 axs[0].plot(xt) ##### 差分變換 df = pd.DataFrame(xt) df_diff1_1 = df.diff() ### 1階差分,步長為1 df_diff1_2 = df.diff(2) ### 1階差分,步長為2 df_diff2 = df_diff1_1.diff() ### 2階差分,步長為1 axs[1].plot(df_diff1_1) axs[2].plot(df_diff1_2) axs[3].plot(df_diff2) plt.show()
二階差分是 對 一階差分 的差分
輸出:非平穩序列、一階差分/步長1、1階差分/步長2、2階差分/步長1
可以看到 原始數據 非平穩,后面的基本上是平穩序列;
平穩性檢測
通過差分變換 可以使得 序列平穩,但是該采用什么樣的差分變換,變換后是否平穩呢?
我們可以通過 ADF 單位根檢驗方法 來檢測序列的平穩性;
時間序列處理
事實上,在處理時間序列時,我們首先要檢測 序列的平穩性,大致流程如下
ADF 平穩性檢測
ADF檢驗總結一句話:如果序列是平穩的,則不存在單位根, 否則就會存在單位根
def adfuller(x, maxlag=None, regression="c", autolag='AIC', store=False, regresults=False): """ Parameters ---------- x : array_like, 1d The data series to test. maxlag : int Maximum lag which is included in test, default 12*(nobs/100)^{1/4}. regression : {'c','ct','ctt','nc'} Constant and trend order to include in regression. * 'c' : constant only (default). * 'ct' : constant and trend. * 'ctt' : constant, and linear and quadratic trend. * 'nc' : no constant, no trend. Returns ------- adf : float The test statistic. pvalue : float MacKinnon's approximate p-value based on MacKinnon (1994, 2010). """
returns:adf 是檢測結果,pvalue 是 p 值
還用 差分變換 那節的例子,來解釋下 ADF 檢測的用法
np.random.seed(12345) ut = np.random.randint(-30, 30, size=(100)) xt = np.cumsum(ut) print(ts.adfuller(xt)) # (-1.5243530203505073, 0.5214317018385488, 0, 99, {'1%': -3.498198082189098, '5%': -2.891208211860468, '10%': -2.5825959973472097}, 845.9136155157069) ##### 差分變換 df = pd.DataFrame(xt) df_diff1_1 = df.diff() ### 1階差分,步長為1 print(ts.adfuller(df_diff1_1[1:])) # (-3.849731498648273, 0.0024375726243445746, 12, 86, {'1%': -3.5087828609430614, '5%': -2.895783561573195, '10%': -2.5850381719848565}, 740.2735055354956) df_diff1_2 = df.diff(2) ### 1階差分,步長為2 print(ts.adfuller(df_diff1_2[2:])) # (-4.012534867488554, 0.001346278712964153, 11, 86, {'1%': -3.5087828609430614, '5%': -2.895783561573195, '10%': -2.5850381719848565}, 736.1426417807885) df_diff2 = df_diff1_1.diff() ### 2階差分,步長為1 print(ts.adfuller(df_diff2[2:])) # (-5.307353752105175, 5.286830381426628e-06, 10, 87, {'1%': -3.5078527246648834, '5%': -2.895382030636155, '10%': -2.584823877658872}, 744.9060722567168)
輸出 第 1 個值我們稱為 test result,第 2 個值我們稱為 p-value;
ADF 檢驗的假設是 存在單位根,有兩種方式檢驗 假設 是否成立:
1. 如果 test result 顯著小於 3 個置信度(1%、5%、10%) 的臨界統計值,說明是 拒絕 原假設的;
2. 如果 p-value 小於 0.05,說明是 拒絕 原假設的;
實例解讀
原始數據(非平穩) 檢測結果為 -1.5,大於三個臨界值 -3.4,-2.8,-2.5,說明 原假設成立,存在單位根,證明為 非平穩序列;
p-value 為 0.5,遠大於 0.05,原假設成立,存在單位根,證明為 非平穩序列;
這個邏輯挺繞的,總結一下,要想 序列平穩,test result 和 p-value 都要小;
參考資料:
https://www.zhihu.com/question/29128649 什么是時間序列模型,什么是弱平穩和嚴格平穩?
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.diff.html 差分
https://www.lizenghai.com/archives/595.html 基於Python的ADF單位根檢驗方法——時間序列平穩檢驗
https://www.zhihu.com/question/25946431 如何將非平穩的時間序列變為平穩的時間序列?
https://blog.csdn.net/qtlyx/article/details/53456480 時間序列分析這件小事(六)--非平穩時間序列與差分
https://blog.csdn.net/dingming001/article/details/73732102 差分變換進階【有空再看看】