J'essaie d'exécuter grangercausalitytests
sur deux séries chronologiques:
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)
Cependant, je reçois
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
et je ne sais pas pourquoi c'est le cas.
Le problème se pose en raison de la parfaite corrélation entre les deux séries dans vos données. D'après le traçage, vous pouvez voir qu'en interne un test de wald est utilisé pour calculer les estimations du maximum de vraisemblance pour les paramètres de la série temporelle. Pour ce faire, une estimation de la matrice de covariance des paramètres (qui est alors proche de zéro) et son inverse est nécessaire (comme vous pouvez également le voir sur la ligne invcov = np.linalg.inv(cov_p)
dans le tracé). Cette matrice proche de zéro est désormais singulière pour un certain décalage maximum (> = 5) et donc le test se bloque. Si vous ajoutez juste un peu de bruit à vos données, l'erreur disparaît:
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
Une autre chose à surveiller est les colonnes en double. Les colonnes en double auront un score de corrélation de 1,0, résultant en une singularité. Sinon, il est également possible que vous ayez 2 fonctionnalités parfaitement corrélées. Et un moyen facile de vérifier cela est avec df.corr()
, et recherchez des paires de colonnes avec corrélation = 1.0.