Waarom krijg ik “LinAlgError: Singular matrix” van grangercausalitytests?

Ik probeer grangercausalitytestsuit te voeren op twee tijdreeksen:

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)

Ik krijg echter

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

en ik weet niet zeker waarom dit het geval is.


Antwoord 1, autoriteit 100%

Het probleem ontstaat door de perfecte correlatie tussen de twee reeksen in uw gegevens. Uit de traceback kunt u zien dat intern een wald-test wordt gebruikt om de maximale waarschijnlijkheidsschattingen voor de parameters van de vertragingstijdreeks te berekenen. Om dit te doen is een schatting van de parameters covariantiematrix (die dan bijna nul is) en zijn inverse nodig (zoals je ook kunt zien in de regel invcov = np.linalg.inv(cov_p)in de traceerbaarheid). Deze matrix van bijna nul is nu enkelvoud voor een maximum lag-getal (>=5) en dus crasht de test. Als u een klein beetje ruis aan uw gegevens toevoegt, verdwijnt de fout:

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

Antwoord 2, autoriteit 18%

Een ander ding om op te letten zijn dubbele kolommen. Dubbele kolommen hebben een correlatiescore van 1,0, wat resulteert in singulariteit. Anders is het ook mogelijk dat u 2 functies hebt die perfect gecorreleerd zijn. En een gemakkelijke manier om dit te controleren is met df.corr(), en zoek naar paren kolommen met correlatie = 1.0.

Other episodes