Skip to content

Commit

Permalink
Merge pull request #5934 from bashtage/pr-5933-5784
Browse files Browse the repository at this point in the history
Backport #5933 and #5784
  • Loading branch information
bashtage committed Jul 12, 2019
2 parents 1fe6147 + ff8d72a commit bf29175
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 53 deletions.
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# https://docs.microsoft.com/en-us/azure/devops/pipelines/process/templates?view=azure-devops#passing-parameters

trigger:
- master
- maintenance/0.10.x

variables:
MKL_NUM_THREADS: 1
Expand Down
6 changes: 4 additions & 2 deletions docs/source/release/version0.10.1.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ providing feedback.

Thanks to all of the contributors for the 0.10 release (based on git log):

.. TODO: Remove if none
* Someone
* Someone Else
* Someone??

These lists of names are automatically generated based on git log, and may not
be complete.
Expand All @@ -41,6 +41,7 @@ Merged Pull Requests

The following Pull Requests were merged since the last release:

* :pr:`5784`: MAINT: implement parts of #5220, deprecate ancient aliases
* :pr:`5892`: BUG: fix pandas compat
* :pr:`5893`: BUG: exponential smoothing - damped trend gives incorrect param, predictions
* :pr:`5895`: DOC: improvements to BayesMixedGLM docs, argument checking
Expand All @@ -49,3 +50,4 @@ The following Pull Requests were merged since the last release:
* :pr:`5917`: BUG: TVTP for Markov regression
* :pr:`5921`: BUG: Ensure exponential smoothers has continuous double data
* :pr:`5930`: BUG: Limit lags in KPSS
* :pr:`5933`: MAINT: Fix test that fails with positive probability
48 changes: 25 additions & 23 deletions statsmodels/sandbox/distributions/tests/test_multivariate.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
import numpy as np
from numpy.testing import (assert_almost_equal, assert_array_almost_equal,
assert_allclose)

from statsmodels.sandbox.distributions.multivariate import (
mvstdtprob, mvstdnormcdf)
mvstdtprob, mvstdnormcdf)
from statsmodels.sandbox.distributions.mv_normal import MVT, MVNormal


Expand Down Expand Up @@ -123,52 +124,53 @@ def setup_class(cls):
cls.mvn3 = mvn3
cls.mvn3c = mvn3c


def test_mvn_pdf(self):
cov3 = self.cov3
mvn3 = self.mvn3
mvn3c = self.mvn3c

r_val = [-7.667977543898155, -6.917977543898155, -5.167977543898155]
assert_array_almost_equal( mvn3.logpdf(cov3), r_val, decimal = 14)
#decimal 18
r_val = [0.000467562492721686, 0.000989829804859273, 0.005696077243833402]
assert_array_almost_equal( mvn3.pdf(cov3), r_val, decimal = 17)
#cheating new mean, same cov, too dangerous, got wrong instance in tests
#mvn3.mean = np.array([0,0,0])
mvn3b = MVNormal(np.array([0,0,0]), cov3)
assert_array_almost_equal(mvn3.logpdf(cov3), r_val, decimal=14)
# decimal 18
r_val = [0.000467562492721686, 0.000989829804859273,
0.005696077243833402]
assert_array_almost_equal(mvn3.pdf(cov3), r_val, decimal=17)

mvn3b = MVNormal(np.array([0, 0, 0]), cov3)
r_val = [0.02914269740502042, 0.02269635555984291, 0.01767593948287269]
assert_array_almost_equal( mvn3b.pdf(cov3), r_val, decimal = 16)
assert_array_almost_equal(mvn3b.pdf(cov3), r_val, decimal=16)

def test_mvt_pdf(self):
def test_mvt_pdf(self, reset_randomstate):
cov3 = self.cov3
mu3 = self.mu3

mvt = MVT((0,0), 1, 5)
assert_almost_equal(mvt.logpdf(np.array([0.,0.])), -1.837877066409345,
mvt = MVT((0, 0), 1, 5)
assert_almost_equal(mvt.logpdf(np.array([0., 0.])), -1.837877066409345,
decimal=15)
assert_almost_equal(mvt.pdf(np.array([0.,0.])), 0.1591549430918953,
assert_almost_equal(mvt.pdf(np.array([0., 0.])), 0.1591549430918953,
decimal=15)

mvt.logpdf(np.array([1.,1.]))-(-3.01552989458359)
mvt.logpdf(np.array([1., 1.])) - (-3.01552989458359)

mvt1 = MVT((0,0), 1, 1)
mvt1.logpdf(np.array([1.,1.]))-(-3.48579549941151) #decimal=16
mvt1 = MVT((0, 0), 1, 1)
mvt1.logpdf(np.array([1., 1.])) - (-3.48579549941151) # decimal=16

rvs = mvt.rvs(100000)
assert_almost_equal(np.cov(rvs, rowvar=0), mvt.cov, decimal=1)
assert_almost_equal(np.cov(rvs, rowvar=False), mvt.cov, decimal=1)

mvt31 = MVT(mu3, cov3, 1)
assert_almost_equal(mvt31.pdf(cov3),
[0.0007276818698165781, 0.0009980625182293658, 0.0027661422056214652],
decimal=17)
[0.0007276818698165781, 0.0009980625182293658,
0.0027661422056214652],
decimal=17)

mvt = MVT(mu3, cov3, 3)
assert_almost_equal(mvt.pdf(cov3),
[0.000863777424247410, 0.001277510788307594, 0.004156314279452241],
decimal=17)
[0.000863777424247410, 0.001277510788307594,
0.004156314279452241],
decimal=17)


if __name__ == '__main__':
import pytest

pytest.main([__file__, '-vvs', '-x', '--pdb'])
60 changes: 59 additions & 1 deletion statsmodels/tools/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,65 @@
from statsmodels.tools.sm_exceptions import CacheWriteWarning
import warnings

__all__ = ['cache_readonly', 'cache_writable']
__all__ = ['cache_readonly', 'cache_writable', 'deprecated_alias']


def deprecated_alias(old_name, new_name, remove_version=None, msg=None,
warning=FutureWarning):
"""
Deprecate attribute in favor of alternative name.
Parameters
----------
old_name : str
Old, deprecated name
new_name : str
New name
remove_version : str, optional
Version that the alias will be removed
msg : str, optional
Message to show. Default is
`old_name` is a deprecated alias for `new_name`
warning : Warning, optional
Warning class to give. Default is FutureWarning.
Notes
-----
Older or less-used classes may not conform to statsmodels naming
conventions. `deprecated_alias` lets us bring them into conformance
without breaking backward-compatibility.
Example
-------
Instances of the `Foo` class have a `nvars` attribute, but it _should_
be called `neqs`:
class Foo(object):
nvars = deprecated_alias('nvars', 'neqs')
def __init__(self, neqs):
self.neqs = neqs
>>> foo = Foo(3)
>>> foo.nvars
__main__:1: FutureWarning: nvars is a deprecated alias for neqs
3
"""

if msg is None:
msg = '%s is a deprecated alias for %s' % (old_name, new_name)
if remove_version is not None:
msg += ', will be removed in version %s' % remove_version

def fget(self):
warnings.warn(msg, warning, stacklevel=2)
return getattr(self, new_name)

def fset(self, value):
warnings.warn(msg, warning, stacklevel=2)
setattr(self, new_name, value)

res = property(fget=fget, fset=fset)
return res


class CachedAttribute(object):
Expand Down
42 changes: 41 additions & 1 deletion statsmodels/tools/tests/test_decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from numpy.testing import assert_equal

from statsmodels.tools.decorators import (
cache_readonly, CacheWriteWarning)
cache_readonly, CacheWriteWarning, deprecated_alias)


def test_cache_readonly():
Expand Down Expand Up @@ -40,3 +40,43 @@ def f(self):
ex.b = -1

assert_equal(ex._cache, dict(b=1,))


def dummy_factory(msg, remove_version, warning):
class Dummy(object):
y = deprecated_alias('y', 'x',
remove_version=remove_version,
msg=msg,
warning=warning)

def __init__(self, y):
self.x = y

return Dummy(1)


@pytest.mark.parametrize('warning', [FutureWarning, UserWarning])
@pytest.mark.parametrize('remove_version', [None, '0.11'])
@pytest.mark.parametrize('msg', ['test message', None])
def test_deprecated_alias(msg, remove_version, warning):
dummy_set = dummy_factory(msg, remove_version, warning)
with pytest.warns(warning) as w:
dummy_set.y = 2
assert dummy_set.x == 2

assert warning.__class__ is w[0].category.__class__

dummy_get = dummy_factory(msg, remove_version, warning)
with pytest.warns(warning) as w:
x = dummy_get.y
assert x == 1

assert warning.__class__ is w[0].category.__class__
message = str(w[0].message)
if not msg:
if remove_version:
assert 'will be removed' in message
else:
assert 'will be removed' not in message
else:
assert msg in message
17 changes: 12 additions & 5 deletions statsmodels/tsa/vector_ar/svar_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import numpy.linalg as npl
from numpy.linalg import slogdet

from statsmodels.tools.decorators import deprecated_alias
from statsmodels.tools.numdiff import approx_hess, approx_fprime
from statsmodels.tsa.vector_ar.irf import IRAnalysis
from statsmodels.tsa.vector_ar.var_model import VARProcess, VARResults
Expand Down Expand Up @@ -54,13 +55,15 @@ class SVAR(tsbase.TimeSeriesModel):
----------
Hamilton (1994) Time Series Analysis
"""

y = deprecated_alias("y", "endog", remove_version="0.11.0")

def __init__(self, endog, svar_type, dates=None,
freq=None, A=None, B=None, missing='none'):
super(SVAR, self).__init__(endog, None, dates, freq, missing=missing)
#(self.endog, self.names,
# self.dates) = data_util.interpret_data(endog, names, dates)

self.y = self.endog #keep alias for now
self.neqs = self.endog.shape[1]

types = ['A', 'B', 'AB']
Expand Down Expand Up @@ -560,16 +563,20 @@ class SVARResults(SVARProcess, VARResults):

_model_type = 'SVAR'

y = deprecated_alias("y", "endog", remove_version="0.11.0")
ys_lagged = deprecated_alias("ys_lagged", "endog_lagged",
remove_version="0.11.0")

def __init__(self, endog, endog_lagged, params, sigma_u, lag_order,
A=None, B=None, A_mask=None, B_mask=None, model=None,
trend='c', names=None, dates=None):

self.model = model
self.y = self.endog = endog #keep alias for now
self.ys_lagged = self.endog_lagged = endog_lagged #keep alias for now
self.endog = endog
self.endog_lagged = endog_lagged
self.dates = dates

self.n_totobs, self.neqs = self.y.shape
self.n_totobs, self.neqs = self.endog.shape
self.nobs = self.n_totobs - lag_order
k_trend = util.get_trendorder(trend)
if k_trend > 0: # make this the polynomial trend order
Expand Down Expand Up @@ -630,7 +637,7 @@ def sirf_errband_mc(self, orth=False, repl=1000, T=10,
Parameters
----------
orth: bool, default False
Compute orthoganalized impulse response error bands
Compute orthogonalized impulse response error bands
repl: int
number of Monte Carlo replications to perform
T: int, default 10
Expand Down
29 changes: 26 additions & 3 deletions statsmodels/tsa/vector_ar/tests/test_var.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
Test VAR Model
"""
import warnings
# pylint: disable=W0612,W0231
from statsmodels.compat.python import (iteritems, StringIO, lrange, BytesIO,
range)

Expand Down Expand Up @@ -39,6 +38,24 @@
DECIMAL_2 = 2


@pytest.fixture()
def bivariate_var_data(reset_randomstate):
"""A bivariate dataset for VAR estimation"""
e = np.random.standard_normal((252, 2))
y = np.zeros_like(e)
y[:2] = e[:2]
for i in range(2, 252):
y[i] = .2 * y[i - 1] + .1 * y[i - 2] + e[i]
return y


@pytest.fixture()
def bivariate_var_result(bivariate_var_data):
"""A bivariate VARResults for reuse"""
mod = VAR(bivariate_var_data)
return mod.fit()


class CheckVAR(object):
# just so pylint won't complain
res1 = None
Expand Down Expand Up @@ -400,10 +417,10 @@ def test_acorr(self):
acorrs = self.res.acorr(10)

def test_forecast(self):
point = self.res.forecast(self.res.y[-5:], 5)
point = self.res.forecast(self.res.endog[-5:], 5)

def test_forecast_interval(self):
y = self.res.y[:-self.p:]
y = self.res.endog[:-self.p:]
point, lower, upper = self.res.forecast_interval(y, 5)

@pytest.mark.matplotlib
Expand Down Expand Up @@ -767,3 +784,9 @@ def test_exog(self):
assert_allclose(fci2, fci1, rtol=1e-12)
assert_allclose(fci3, fci1, rtol=1e-12)
assert_allclose(fci3, fci2, rtol=1e-12)


@pytest.mark.parametrize('attr', ['y', 'ys_lagged'])
def test_deprecated_attributes_varresults(bivariate_var_result, attr):
with pytest.warns(FutureWarning):
getattr(bivariate_var_result, attr)

0 comments on commit bf29175

Please sign in to comment.