Skip to content

Commit 5134c97

Browse files
committed
BUG: Allow pandas to wrap VAR covariance
Extend PandasData to allow cov_names to be set separately from param_names closes statsmodels#5305 closes statsmodels#2270
1 parent 9298953 commit 5134c97

File tree

2 files changed

+39
-32
lines changed

2 files changed

+39
-32
lines changed

statsmodels/base/data.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class ModelData(object):
5353
appropriate form
5454
"""
5555
_param_names = None
56+
_cov_names = None
5657

5758
def __init__(self, endog, exog=None, missing='none', hasconst=None,
5859
**kwargs):
@@ -350,6 +351,24 @@ def param_names(self):
350351
def param_names(self, values):
351352
self._param_names = values
352353

354+
@property
355+
def cov_names(self):
356+
"""
357+
Labels for covariance matrices
358+
359+
In multidimensional models, each dimension of a covariance matrix
360+
differs from the number of param_names.
361+
362+
If not set, returns param_names
363+
"""
364+
# for handling names of covariance names in multidimensional models
365+
return self._cov_names or self.param_names
366+
367+
@cov_names.setter
368+
def cov_names(self, value):
369+
# for handling names of covariance names in multidimensional models
370+
self._cov_names = value
371+
353372
@cache_readonly
354373
def row_labels(self):
355374
exog = self.orig_exog
@@ -531,8 +550,7 @@ def attach_columns_eq(self, result):
531550
return DataFrame(result, index=self.xnames, columns=self.ynames)
532551

533552
def attach_cov(self, result):
534-
return DataFrame(result, index=self.param_names,
535-
columns=self.param_names)
553+
return DataFrame(result, index=self.cov_names, columns=self.cov_names)
536554

537555
def attach_cov_eq(self, result):
538556
return DataFrame(result, index=self.ynames, columns=self.ynames)

statsmodels/tsa/vector_ar/var_model.py

Lines changed: 19 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,32 @@
66
----------
77
Lütkepohl (2005) New Introduction to Multiple Time Series Analysis
88
"""
9-
9+
from statsmodels.compat.pandas import deprecate_kwarg
1010
from statsmodels.compat.python import (range, lrange, string_types,
1111
StringIO, iteritems)
12-
from statsmodels.compat.pandas import deprecate_kwarg
12+
1313
from collections import defaultdict
1414

1515
import numpy as np
16-
import scipy.stats as stats
1716
import scipy.linalg
17+
import scipy.stats as stats
1818

19+
import statsmodels.base.wrapper as wrap
20+
from statsmodels.tsa.base.tsa_model import (TimeSeriesModel,
21+
TimeSeriesResultsWrapper)
22+
import statsmodels.tsa.tsatools as tsa
1923
from statsmodels.iolib.table import SimpleTable
2024
from statsmodels.tools.decorators import cache_readonly, deprecated_alias
25+
from statsmodels.tools.linalg import logdet_symm
2126
from statsmodels.tools.sm_exceptions import OutputWarning
2227
from statsmodels.tools.tools import chain_dot
23-
from statsmodels.tools.linalg import logdet_symm
2428
from statsmodels.tsa.tsatools import vec, unvec, duplication_matrix
29+
from statsmodels.tsa.vector_ar import output, plotting, util
2530
from statsmodels.tsa.vector_ar.hypothesis_test_results import \
2631
CausalityTestResults, NormalityTestResults, WhitenessTestResults
27-
2832
from statsmodels.tsa.vector_ar.irf import IRAnalysis
2933
from statsmodels.tsa.vector_ar.output import VARSummary
3034

31-
import statsmodels.tsa.tsatools as tsa
32-
from statsmodels.tsa.vector_ar import output, plotting, util
33-
import statsmodels.tsa.base.tsa_model as tsbase
34-
import statsmodels.base.wrapper as wrap
35-
3635

3736
# -------------------------------------------------------------------------------
3837
# VAR process routines
@@ -495,7 +494,7 @@ def __str__(self):
495494
# VARProcess class: for known or unknown VAR process
496495

497496

498-
class VAR(tsbase.TimeSeriesModel):
497+
class VAR(TimeSeriesModel):
499498
r"""
500499
Fit VAR(p) process and do lag order selection
501500
@@ -641,7 +640,9 @@ def fit(self, maxlags=None, method='ols', ic=None, trend='c',
641640
self.data.xnames = (self.data.xnames[:k_trend] +
642641
x_names_to_add +
643642
self.data.xnames[k_trend:])
644-
643+
self.data.cov_names = ['.'.join((str(yn), str(xn)))
644+
for xn in self.data.xnames
645+
for yn in self.data.ynames]
645646
return self._estimate_var(lags, trend=trend)
646647

647648
def _estimate_var(self, lags, offset=0, trend='c'):
@@ -1347,7 +1348,6 @@ def sigma_u_mle(self):
13471348
"""
13481349
return self.sigma_u * self.df_resid / self.nobs
13491350

1350-
@cache_readonly
13511351
def cov_params(self):
13521352
"""Estimated variance-covariance of model coefficients
13531353
@@ -1359,20 +1359,9 @@ def cov_params(self):
13591359
Adjusted to be an unbiased estimator
13601360
Ref: Lütkepohl p.74-75
13611361
"""
1362-
import warnings
1363-
warnings.warn("For consistency with other statmsodels models, "
1364-
"starting in version 0.11.0 `VARResults.cov_params` "
1365-
"will be a method instead of a property.",
1366-
category=FutureWarning)
13671362
z = self.endog_lagged
13681363
return np.kron(scipy.linalg.inv(np.dot(z.T, z)), self.sigma_u)
13691364

1370-
def _cov_params(self):
1371-
"""Wrapper to avoid FutureWarning. Remove after 0.11"""
1372-
import warnings
1373-
with warnings.catch_warnings(record=True):
1374-
return self.cov_params
1375-
13761365
def cov_ybar(self):
13771366
r"""Asymptotically consistent estimate of covariance of the sample mean
13781367
@@ -1405,7 +1394,8 @@ def _cov_alpha(self):
14051394
Estimated covariance matrix of model coefficients w/o exog
14061395
"""
14071396
# drop exog
1408-
return self._cov_params()[self.k_exog*self.neqs:, self.k_exog*self.neqs:]
1397+
kn = self.k_exog * self.neqs
1398+
return self.cov_params()[kn:, kn:]
14091399

14101400
@cache_readonly
14111401
def _cov_sigma(self):
@@ -1427,7 +1417,7 @@ def llf(self):
14271417
def stderr(self):
14281418
"""Standard errors of coefficients, reshaped to match in size
14291419
"""
1430-
stderr = np.sqrt(np.diag(self._cov_params()))
1420+
stderr = np.sqrt(np.diag(self.cov_params()))
14311421
return stderr.reshape((self.df_model, self.neqs), order='C')
14321422

14331423
bse = stderr # statsmodels interface?
@@ -1829,7 +1819,7 @@ def test_causality(self, caused, causing=None, kind='f', signif=0.05):
18291819

18301820
# Lütkepohl 3.6.5
18311821
Cb = np.dot(C, vec(self.params.T))
1832-
middle = scipy.linalg.inv(chain_dot(C, self._cov_params(), C.T))
1822+
middle = scipy.linalg.inv(chain_dot(C, self.cov_params(), C.T))
18331823

18341824
# wald statistic
18351825
lam_wald = statistic = chain_dot(Cb, middle, Cb)
@@ -2145,12 +2135,11 @@ class VARResultsWrapper(wrap.ResultsWrapper):
21452135
'tvalues': 'columns_eq', 'sigma_u': 'cov_eq',
21462136
'sigma_u_mle': 'cov_eq',
21472137
'stderr': 'columns_eq'}
2148-
_wrap_attrs = wrap.union_dicts(tsbase.TimeSeriesResultsWrapper._wrap_attrs,
2138+
_wrap_attrs = wrap.union_dicts(TimeSeriesResultsWrapper._wrap_attrs,
21492139
_attrs)
21502140
_methods = {}
2151-
_wrap_methods = wrap.union_dicts(tsbase.TimeSeriesResultsWrapper._wrap_methods,
2141+
_wrap_methods = wrap.union_dicts(TimeSeriesResultsWrapper._wrap_methods,
21522142
_methods)
2153-
_wrap_methods.pop('cov_params') # not yet a method in VARResults
21542143
wrap.populate_wrapper(VARResultsWrapper, VARResults) # noqa:E305
21552144

21562145

0 commit comments

Comments
 (0)