2つの時系列でgrangercausalitytests
を実行しようとしています。
import numpy as np
import pandas as pd
from statsmodels.tsa.stattools import grangercausalitytests
n = 1000
ls = np.linspace(0, 2*np.pi, n)
df1 = pd.DataFrame(np.sin(ls))
df2 = pd.DataFrame(2*np.sin(1+ls))
df = pd.concat([df1, df2], axis=1)
df.plot()
grangercausalitytests(df, maxlag=20)
しかし、私は得ています
Granger Causality
number of lags (no zero) 1
ssr based F test: F=272078066917221398041264652288.0000, p=0.0000 , df_denom=996, df_num=1
ssr based chi2 test: chi2=272897579166972095424217743360.0000, p=0.0000 , df=1
likelihood ratio test: chi2=60811.2671, p=0.0000 , df=1
parameter F test: F=272078066917220553616334520320.0000, p=0.0000 , df_denom=996, df_num=1
Granger Causality
number of lags (no zero) 2
ssr based F test: F=7296.6976, p=0.0000 , df_denom=995, df_num=2
ssr based chi2 test: chi2=14637.3954, p=0.0000 , df=2
likelihood ratio test: chi2=2746.0362, p=0.0000 , df=2
parameter F test: F=13296850090491009488285469769728.0000, p=0.0000 , df_denom=995, df_num=2
...
/usr/local/lib/python3.5/dist-packages/numpy/linalg/linalg.py in _raise_linalgerror_singular(err, flag)
88
89 def _raise_linalgerror_singular(err, flag):
---> 90 raise LinAlgError("Singular matrix")
91
92 def _raise_linalgerror_nonposdef(err, flag):
LinAlgError: Singular matrix
なぜそうなのかよくわかりません。
この問題は、データ内の2つのシリーズ間の完全な相関関係が原因で発生します。トレースバックから、ラグタイムシリーズのパラメーターの最尤推定値を計算するために内部でウォルドテストが使用されていることがわかります。これを行うには、パラメーターの共分散行列(これはゼロに近い)とその逆数の推定が必要です(トレースバックのinvcov = np.linalg.inv(cov_p)
の行でも確認できます)。このゼロに近い行列は、いくつかの最大ラグ数(> = 5)では特異であるため、テストがクラッシュします。データにほんの少しのノイズを追加すると、エラーは消えます。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.stattools import grangercausalitytests
n = 1000
ls = np.linspace(0, 2*np.pi, n)
df1Clean = pd.DataFrame(np.sin(ls))
df2Clean = pd.DataFrame(2*np.sin(ls+1))
dfClean = pd.concat([df1Clean, df2Clean], axis=1)
dfDirty = dfClean+0.00001*np.random.Rand(n, 2)
grangercausalitytests(dfClean, maxlag=20, verbose=False) # Raises LinAlgError
grangercausalitytests(dfDirty, maxlag=20, verbose=False) # Runs fine
注目すべきもう1つのことは、列の重複です。列が重複すると相関スコアが1.0になり、特異性が生じます。そうでなければ、完全に相関している2つの機能がある可能性もあります。これをチェックする簡単な方法は、df.corr()
を使用して、correlation = 1.0の列のペアを探すことです。