Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

refactor stats tests a bit #3101

Merged
merged 9 commits into from

3 participants

@ev-br
Collaborator

trim down on code duplication, group same [or very similar] tests etc.
Generally try to make it a little easier to see what is and what is not covered by the test suite.

@coveralls

Coverage Status

Coverage remained the same when pulling 8c5f94f on ev-br:stats_tests into 6039369 on scipy:master.

@rgommers
Owner

All looks good to me. Thanks Evgeni.

@rgommers rgommers merged commit c4314b0 into scipy:master
@ev-br ev-br deleted the ev-br:stats_tests branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Nov 30, 2013
  1. @ev-br
  2. @ev-br

    MAINT: remove kolmogorov_check, duplicated test

    ev-br authored
    * kolmogorov_check is not run, superseded by check_distribution
    * remove docstrings from tests
    * remove one of the two copies of check_edge_support
  3. @ev-br
  4. @ev-br
  5. @ev-br
  6. @ev-br

    TST: reenable test for _ppf not NaN

    ev-br authored
    and move it to test_continuous_basic
  7. @ev-br

    MAINT: move regression tests from test_continuous_extra

    ev-br authored
    remove test_continuous_extra as it does not contain anything useful
    anymore
  8. @ev-br
  9. @ev-br
This page is out of date. Refresh to see the latest.
View
16 scipy/stats/distributions.py
@@ -4378,17 +4378,17 @@ class invweibull_gen(rv_continuous):
"""
def _pdf(self, x, c):
- xc1 = x**(-c-1.0)
- xc2 = x**(-c)
+ xc1 = np.power(x, -c - 1.0)
+ xc2 = np.power(x, -c)
xc2 = exp(-xc2)
- return c*xc1*xc2
+ return c * xc1 * xc2
def _cdf(self, x, c):
- xc1 = x**(-c)
+ xc1 = np.power(x, -c)
return exp(-xc1)
def _ppf(self, q, c):
- return pow(-log(q),asarray(-1.0/c))
+ return np.power(-log(q), -1.0/c)
def _munp(self, n, c):
return special.gamma(1 - n / c)
@@ -7270,10 +7270,10 @@ def _argcheck(self, p):
return (p <= 1) & (p >= 0)
def _pmf(self, k, p):
- return (1-p)**(k-1) * p
+ return np.power(1-p, k-1) * p
def _logpmf(self, k, p):
- return (k-1)*log(1-p) + log(p)
+ return (k-1) * log(1-p) + log(p)
def _cdf(self, x, p):
k = floor(x)
@@ -7439,7 +7439,7 @@ def _argcheck(self, p):
return (p > 0) & (p < 1)
def _pmf(self, k, p):
- return -p**k * 1.0 / k / log(1 - p)
+ return -np.power(p, k) * 1.0 / k / log(1 - p)
def _stats(self, p):
r = log(1 - p)
View
78 scipy/stats/tests/common_tests.py
@@ -1,7 +1,14 @@
from __future__ import division, print_function, absolute_import
+import inspect
+import warnings
+
import numpy as np
import numpy.testing as npt
+from distutils.version import LooseVersion
+from scipy import stats
+
+NUMPY_BELOW_1_7 = LooseVersion(np.version.version) < LooseVersion('1.7')
def check_normalization(distfn, args, distname):
@@ -71,3 +78,74 @@ def check_kurt_expect(distfn, arg, m, v, k, msg):
err_msg=msg + ' - kurtosis')
else:
npt.assert_(np.isnan(k))
+
+
+def check_entropy(distfn, arg, msg):
+ ent = distfn.entropy(*arg)
+ npt.assert_(not np.isnan(ent), msg + 'test Entropy is nan')
+
+
+def check_private_entropy(distfn, args, superclass):
+ # compare a generic _entropy with the distribution-specific implementation
+ npt.assert_allclose(distfn._entropy(*args),
+ superclass._entropy(distfn, *args))
+
+
+def check_edge_support(distfn, args):
+ # Make sure the x=self.a and self.b are handled correctly.
+ x = [distfn.a, distfn.b]
+ if isinstance(distfn, stats.rv_continuous):
+ npt.assert_equal(distfn.cdf(x, *args), [0.0, 1.0])
+ npt.assert_equal(distfn.logcdf(x, *args), [-np.inf, 0.0])
+
+ npt.assert_equal(distfn.sf(x, *args), [1.0, 0.0])
+ npt.assert_equal(distfn.logsf(x, *args), [0.0, -np.inf])
+
+ if isinstance(distfn, stats.rv_discrete):
+ x = [distfn.a - 1, distfn.b]
+ npt.assert_equal(distfn.ppf([0.0, 1.0], *args), x)
+ npt.assert_equal(distfn.isf([0.0, 1.0], *args), x[::-1])
+
+ # out-of-bounds for isf & ppf
+ npt.assert_(np.isnan(distfn.isf([-1, 2], *args)).all())
+ npt.assert_(np.isnan(distfn.ppf([-1, 2], *args)).all())
+
+
+def check_named_args(distfn, x, shape_args, defaults, meths):
+ ## Check calling w/ named arguments.
+
+ # check consistency of shapes, numargs and _parse signature
+ signature = inspect.getargspec(distfn._parse_args)
+ npt.assert_(signature.varargs is None)
+ npt.assert_(signature.keywords is None)
+ npt.assert_(signature.defaults == defaults)
+
+ shape_argnames = signature.args[1:-len(defaults)] # self, a, b, loc=0, scale=1
+ if distfn.shapes:
+ shapes_ = distfn.shapes.replace(',', ' ').split()
+ else:
+ shapes_ = ''
+ npt.assert_(len(shapes_) == distfn.numargs)
+ npt.assert_(len(shapes_) == len(shape_argnames))
+
+ # check calling w/ named arguments
+ shape_args = list(shape_args)
+
+ vals = [meth(x, *shape_args) for meth in meths]
+ npt.assert_(np.all(np.isfinite(vals)))
+
+ names, a, k = shape_argnames[:], shape_args[:], {}
+ while names:
+ k.update({names.pop(): a.pop()})
+ v = [meth(x, *a, **k) for meth in meths]
+ npt.assert_array_equal(vals, v)
+ if not 'n' in k.keys():
+ # `n` is first parameter of moment(), so can't be used as named arg
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore", UserWarning)
+ npt.assert_equal(distfn.moment(1, *a, **k),
+ distfn.moment(1, *shape_args))
+
+ # unknown arguments should not go through:
+ k.update({'kaboom': 42})
+ npt.assert_raises(TypeError, distfn.cdf, x, **k)
View
165 scipy/stats/tests/test_continuous_basic.py
@@ -1,14 +1,13 @@
from __future__ import division, print_function, absolute_import
-import warnings
-import inspect
-
import numpy as np
import numpy.testing as npt
from scipy import stats
from common_tests import (check_normalization, check_moment, check_mean_expect,
- check_var_expect, check_skew_expect, check_kurt_expect)
+ check_var_expect, check_skew_expect, check_kurt_expect,
+ check_entropy, check_private_entropy, NUMPY_BELOW_1_7,
+ check_edge_support, check_named_args)
"""
Test all continuous distributions.
@@ -187,15 +186,10 @@ def test_cont_basic():
rvs = distfn.rvs(size=sn, *arg)
sm = rvs.mean()
sv = rvs.var()
- skurt = stats.kurtosis(rvs)
- sskew = stats.skew(rvs)
m, v = distfn.stats(*arg)
yield check_sample_meanvar_, distfn, arg, m, v, sm, sv, sn, distname + \
'sample mean test'
- # the sample skew kurtosis test has known failures, not very good distance measure
- # yield check_sample_skew_kurt, distfn, arg, sskew, skurt, distname
- yield check_moment, distfn, arg, m, v, distname
yield check_cdf_ppf, distfn, arg, distname
yield check_sf_isf, distfn, arg, distname
yield check_pdf, distfn, arg, distname
@@ -215,17 +209,20 @@ def test_cont_basic():
x = spec_x.get(distname, 0.5)
yield check_named_args, distfn, x, arg, locscale_defaults, meths
- # this asserts the vectorization of _entropy w/ no shape parameters
- # NB: broken for older versions of numpy
+ # Entropy
+ skp = npt.dec.skipif
+ yield check_entropy, distfn, arg, distname
+
if distfn.numargs == 0:
- if np.__version__ > '1.7':
- yield check_vecentropy, distfn, arg
- # compare a generic _entropy w/ distribution-specific implementation,
- # if available
+ yield skp(NUMPY_BELOW_1_7)(check_vecentropy), distfn, arg
if distfn.__class__._entropy != stats.rv_continuous._entropy:
- yield check_private_entropy, distfn, arg
+ yield check_private_entropy, distfn, arg, stats.rv_continuous
+
yield check_edge_support, distfn, arg
+ knf = npt.dec.knownfailureif
+ yield knf(distname == 'truncnorm')(check_ppf_private), distfn, arg,\
+ distname
@npt.dec.slow
def test_cont_basic_slow():
@@ -239,15 +236,9 @@ def test_cont_basic_slow():
rvs = distfn.rvs(size=sn,*arg)
sm = rvs.mean()
sv = rvs.var()
- skurt = stats.kurtosis(rvs)
- sskew = stats.skew(rvs)
m, v = distfn.stats(*arg)
yield check_sample_meanvar_, distfn, arg, m, v, sm, sv, sn, distname + \
'sample mean test'
- # the sample skew kurtosis test has known failures, not very good distance measure
- # yield check_sample_skew_kurt, distfn, arg, sskew, skurt, distname
- # vonmises and ksone are not supposed to fully work
- yield check_moment, distfn, arg, m, v, distname
yield check_cdf_ppf, distfn, arg, distname
yield check_sf_isf, distfn, arg, distname
yield check_pdf, distfn, arg, distname
@@ -270,15 +261,16 @@ def test_cont_basic_slow():
arg = (3,)
yield check_named_args, distfn, x, arg, locscale_defaults, meths
- # this asserts the vectorization of _entropy w/ no shape parameters
- # NB: broken for older versions of numpy
+ # Entropy
+ skp = npt.dec.skipif
+ ks_cond = distname in ['ksone', 'kstwobign']
+ yield skp(ks_cond)(check_entropy), distfn, arg, distname
+
if distfn.numargs == 0:
- if np.__version__ > '1.7':
- yield check_vecentropy, distfn, arg
- # compare a generic _entropy w/ distribution-specific implementation,
- # if available
+ yield skp(NUMPY_BELOW_1_7)(check_vecentropy), distfn, arg
if distfn.__class__._entropy != stats.rv_continuous._entropy:
- yield check_private_entropy, distfn, arg
+ yield check_private_entropy, distfn, arg, stats.rv_continuous
+
yield check_edge_support, distfn, arg
@@ -297,6 +289,8 @@ def test_moments():
yield knf(cond2, msg)(check_var_expect), distfn, arg, m, v, distname
yield knf(cond2, msg)(check_skew_expect), distfn, arg, m, v, s, distname
yield knf(cond2, msg)(check_kurt_expect), distfn, arg, m, v, k, distname
+ yield check_loc_scale, distfn, arg, m, v, distname
+ yield check_moment, distfn, arg, m, v, distname
def check_sample_meanvar_(distfn, arg, m, v, sm, sv, sn, msg):
@@ -308,40 +302,32 @@ def check_sample_meanvar_(distfn, arg, m, v, sm, sv, sn, msg):
def check_sample_mean(sm,v,n, popmean):
- """
-from stats.stats.ttest_1samp(a, popmean):
-Calculates the t-obtained for the independent samples T-test on ONE group
-of scores a, given a population mean.
-
-Returns: t-value, two-tailed prob
-"""
-## a = asarray(a)
-## x = np.mean(a)
-## v = np.var(a, ddof=1)
-## n = len(a)
+ # from stats.stats.ttest_1samp(a, popmean):
+ # Calculates the t-obtained for the independent samples T-test on ONE group
+ # of scores a, given a population mean.
+ #
+ # Returns: t-value, two-tailed prob
df = n-1
svar = ((n-1)*v) / float(df) # looks redundant
- t = (sm-popmean)/np.sqrt(svar*(1.0/n))
- prob = stats.betai(0.5*df,0.5,df/(df+t*t))
+ t = (sm-popmean) / np.sqrt(svar*(1.0/n))
+ prob = stats.betai(0.5*df, 0.5, df/(df+t*t))
# return t,prob
- npt.assert_(prob > 0.01, 'mean fail, t,prob = %f, %f, m,sm=%f,%f' % (t,prob,popmean,sm))
+ npt.assert_(prob > 0.01, 'mean fail, t,prob = %f, %f, m, sm=%f,%f' %
+ (t, prob, popmean, sm))
def check_sample_var(sv,n, popvar):
- '''
-two-sided chisquare test for sample variance equal to hypothesized variance
- '''
+ # two-sided chisquare test for sample variance equal to hypothesized variance
df = n-1
chi2 = (n-1)*popvar/float(popvar)
pval = stats.chisqprob(chi2,df)*2
- npt.assert_(pval > 0.01, 'var fail, t,pval = %f, %f, v,sv=%f,%f' % (chi2,pval,popvar,sv))
+ npt.assert_(pval > 0.01, 'var fail, t, pval = %f, %f, v, sv=%f, %f' %
+ (chi2,pval,popvar,sv))
def check_sample_skew_kurt(distfn, arg, ss, sk, msg):
skew,kurt = distfn.stats(moments='sk',*arg)
-## skew = distfn.stats(moment='s',*arg)[()]
-## kurt = distfn.stats(moment='k',*arg)[()]
check_sample_meanvar(sk, kurt, msg + 'sample kurtosis test')
check_sample_meanvar(ss, skew, msg + 'sample skew test')
@@ -426,79 +412,18 @@ def check_distribution_rvs(dist, args, alpha, rvs):
def check_vecentropy(distfn, args):
npt.assert_equal(distfn.vecentropy(*args), distfn._entropy(*args))
+@npt.dec.skipif(NUMPY_BELOW_1_7)
+def check_loc_scale(distfn, arg, m, v, msg):
+ loc, scale = 10.0, 10.0
+ mt, vt = distfn.stats(loc=loc, scale=scale, *arg)
+ npt.assert_allclose(m*scale + loc, mt)
+ npt.assert_allclose(v*scale*scale, vt)
-def check_named_args(distfn, x, shape_args, defaults, meths):
- """Check calling w/ named arguments."""
-
- # check consistency of shapes, numargs and _parse signature
- signature = inspect.getargspec(distfn._parse_args)
- npt.assert_(signature.varargs is None)
- npt.assert_(signature.keywords is None)
- npt.assert_(signature.defaults == defaults)
-
- shape_argnames = signature.args[1:-len(defaults)] # self, a, b, loc=0, scale=1
- if distfn.shapes:
- shapes_ = distfn.shapes.replace(',',' ').split()
- else:
- shapes_ = ''
- npt.assert_(len(shapes_) == distfn.numargs)
- npt.assert_(len(shapes_) == len(shape_argnames))
-
- # check calling w/ named arguments
- shape_args = list(shape_args)
-
- vals = [meth(x, *shape_args) for meth in meths]
- npt.assert_(np.all(np.isfinite(vals)))
-
- names, a, k = shape_argnames[:], shape_args[:], {}
- while names:
- k.update({names.pop(): a.pop()})
- v = [meth(x, *a, **k) for meth in meths]
- npt.assert_array_equal(vals, v)
- if not 'n' in k.keys():
- # `n` is first parameter of moment(), so can't be used as named arg
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", UserWarning)
- npt.assert_equal(distfn.moment(3, *a, **k),
- distfn.moment(3, *shape_args))
-
- # unknown arguments should not go through:
- k.update({'kaboom': 42})
- npt.assert_raises(TypeError, distfn.cdf, x, **k)
-
-
-def check_edge_support(distfn, args):
- """Make sure the x=self.a and self.b are handled correctly."""
- x = [distfn.a, distfn.b]
- npt.assert_equal(distfn.cdf(x, *args), [0.0, 1.0])
- npt.assert_equal(distfn.logcdf(x, *args), [-np.inf, 0.0])
-
- npt.assert_equal(distfn.sf(x, *args), [1.0, 0.0])
- npt.assert_equal(distfn.logsf(x, *args), [0.0, -np.inf])
-
- npt.assert_equal(distfn.ppf([0.0, 1.0], *args), x)
- npt.assert_equal(distfn.isf([0.0, 1.0], *args), x[::-1])
- # pdf(x=[a, b], *args) depends on the distribution
-
-
-def check_private_entropy(distfn, args):
- # compare a generic _entropy with the distribution-specific implementation
- npt.assert_allclose(distfn._entropy(*args),
- stats.rv_continuous._entropy(distfn, *args))
-
-
-def check_edge_support(distfn, args):
- """Make sure the x=self.a and self.b are handled correctly."""
- x = [distfn.a, distfn.b]
- npt.assert_equal(distfn.cdf(x, *args), [0.0, 1.0])
- npt.assert_equal(distfn.logcdf(x, *args), [-np.inf, 0.0])
-
- npt.assert_equal(distfn.sf(x, *args), [1.0, 0.0])
- npt.assert_equal(distfn.logsf(x, *args), [0.0, -np.inf])
- npt.assert_equal(distfn.ppf([0.0, 1.0], *args), x)
- npt.assert_equal(distfn.isf([0.0, 1.0], *args), x[::-1])
- # pdf(x=[a, b], *args) depends on the distribution
+def check_ppf_private(distfn, arg, msg):
+ #fails by design for truncnorm self.nb not defined
+ ppfs = distfn._ppf(np.array([0.1, 0.5, 0.9]), *arg)
+ npt.assert_(not np.any(np.isnan(ppfs)), msg + 'ppf private is nan')
if __name__ == "__main__":
View
164 scipy/stats/tests/test_continuous_extra.py
@@ -1,164 +0,0 @@
-# contains additional tests for continuous distributions
-#
-# NOTE: one test, _est_cont_skip, that is renamed so that nose doesn't
-# run it,
-# 6 distributions return nan for entropy
-# truncnorm fails by design for private method _ppf test
-from __future__ import division, print_function, absolute_import
-
-import warnings
-
-import numpy.testing as npt
-import numpy as np
-
-from scipy import stats
-
-from test_continuous_basic import distcont
-
-DECIMAL = 5
-
-
-@npt.dec.slow
-def test_cont_extra():
- for distname, arg in distcont[:]:
- distfn = getattr(stats, distname)
-
- yield check_ppf_limits, distfn, arg, distname + \
- ' ppf limit test'
- yield check_isf_limits, distfn, arg, distname + \
- ' isf limit test'
- yield check_loc_scale, distfn, arg, distname + \
- ' loc, scale test'
-
-
-@npt.dec.slow
-def _est_cont_skip():
- for distname, arg in distcont:
- distfn = getattr(stats, distname)
- #entropy test checks only for isnan, currently 6 isnan left
- yield check_entropy, distfn, arg, distname + \
- ' entropy nan test'
- # _ppf test has 1 failure be design
- yield check_ppf_private, distfn, arg, distname + \
- ' _ppf private test'
-
-
-def test_540_567():
- # test for nan returned in tickets 540, 567
- npt.assert_almost_equal(stats.norm.cdf(-1.7624320982),0.03899815971089126,
- decimal=10, err_msg='test_540_567')
- npt.assert_almost_equal(stats.norm.cdf(-1.7624320983),0.038998159702449846,
- decimal=10, err_msg='test_540_567')
- npt.assert_almost_equal(stats.norm.cdf(1.38629436112, loc=0.950273420309,
- scale=0.204423758009),0.98353464004309321,
- decimal=10, err_msg='test_540_567')
-
-
-def check_ppf_limits(distfn,arg,msg):
- below,low,upp,above = distfn.ppf([-1,0,1,2], *arg)
- #print distfn.name, distfn.a, low, distfn.b, upp
- #print distfn.name,below,low,upp,above
- assert_equal_inf_nan(distfn.a,low, msg + 'ppf lower bound')
- assert_equal_inf_nan(distfn.b,upp, msg + 'ppf upper bound')
- npt.assert_(np.isnan(below), msg + 'ppf out of bounds - below')
- npt.assert_(np.isnan(above), msg + 'ppf out of bounds - above')
-
-
-def check_ppf_private(distfn,arg,msg):
- #fails by design for trunk norm self.nb not defined
- ppfs = distfn._ppf(np.array([0.1,0.5,0.9]), *arg)
- npt.assert_(not np.any(np.isnan(ppfs)), msg + 'ppf private is nan')
-
-
-def check_isf_limits(distfn,arg,msg):
- below,low,upp,above = distfn.isf([-1,0,1,2], *arg)
- #print distfn.name, distfn.a, low, distfn.b, upp
- #print distfn.name,below,low,upp,above
- assert_equal_inf_nan(distfn.a,upp, msg + 'isf lower bound')
- assert_equal_inf_nan(distfn.b,low, msg + 'isf upper bound')
- npt.assert_(np.isnan(below), msg + 'isf out of bounds - below')
- npt.assert_(np.isnan(above), msg + 'isf out of bounds - above')
-
-
-def check_loc_scale(distfn,arg,msg):
- m,v = distfn.stats(*arg)
- loc, scale = 10.0, 10.0
- mt,vt = distfn.stats(loc=loc, scale=scale, *arg)
- assert_equal_inf_nan(m*scale+loc,mt,msg + 'mean')
- assert_equal_inf_nan(v*scale*scale,vt,msg + 'var')
-
-
-def check_entropy(distfn,arg,msg):
- ent = distfn.entropy(*arg)
- #print 'Entropy =', ent
- npt.assert_(not np.isnan(ent), msg + 'test Entropy is nan')
-
-
-def assert_equal_inf_nan(v1,v2,msg):
- npt.assert_(not np.isnan(v1))
- if not np.isinf(v1):
- npt.assert_almost_equal(v1, v2, decimal=DECIMAL, err_msg=msg +
- ' - finite')
- else:
- npt.assert_(np.isinf(v2) or np.isnan(v2),
- msg + ' - infinite, v2=%s' % str(v2))
-
-
-def test_erlang_runtimewarning():
- # erlang should generate a RuntimeWarning if a non-integer
- # shape parameter is used.
- with warnings.catch_warnings():
- warnings.simplefilter("error", RuntimeWarning)
-
- # The non-integer shape parameter 1.3 should trigger a RuntimeWarning
- npt.assert_raises(RuntimeWarning,
- stats.erlang.rvs, 1.3, loc=0, scale=1, size=4)
-
- # Calling the fit method with `f0` set to an integer should
- # *not* trigger a RuntimeWarning. It should return the same
- # values as gamma.fit(...).
- data = [0.5, 1.0, 2.0, 4.0]
- result_erlang = stats.erlang.fit(data, f0=1)
- result_gamma = stats.gamma.fit(data, f0=1)
- npt.assert_allclose(result_erlang, result_gamma, rtol=1e-3)
-
-
-@npt.dec.slow
-def test_rdist_cdf_gh1285():
- # check workaround in rdist._cdf for issue gh-1285.
- distfn = stats.rdist
- values = [0.001, 0.5, 0.999]
- npt.assert_almost_equal(distfn.cdf(distfn.ppf(values, 541.0), 541.0),
- values, decimal=5)
-
-
-def test_rice_zero_b():
- # rice distribution should work with b=0, cf gh-2164
- x = [0.2, 1., 5.]
- npt.assert_(np.isfinite(stats.rice.pdf(x, b=0.)).all())
- npt.assert_(np.isfinite(stats.rice.logpdf(x, b=0.)).all())
- npt.assert_(np.isfinite(stats.rice.cdf(x, b=0.)).all())
- npt.assert_(np.isfinite(stats.rice.logcdf(x, b=0.)).all())
-
- q = [0.1, 0.1, 0.5, 0.9]
- npt.assert_(np.isfinite(stats.rice.ppf(q, b=0.)).all())
-
- mvsk = stats.rice.stats(0, moments='mvsk')
- npt.assert_(np.isfinite(mvsk).all())
-
- # furthermore, pdf is continuous as b\to 0
- # rice.pdf(x, b\to 0) = x exp(-x^2/2) + O(b^2)
- # see e.g. Abramovich & Stegun 9.6.7 & 9.6.10
- b = 1e-8
- npt.assert_allclose(stats.rice.pdf(x, 0), stats.rice.pdf(x, b),
- atol=b, rtol=0)
-
-
-def test_rice_rvs():
- rvs = stats.rice.rvs
- npt.assert_equal(rvs(b=3.).size, 1)
- npt.assert_equal(rvs(b=3., size=(3, 5)).shape, (3, 5))
-
-
-if __name__ == "__main__":
- npt.run_module_suite()
View
108 scipy/stats/tests/test_discrete_basic.py
@@ -1,14 +1,14 @@
from __future__ import division, print_function, absolute_import
-import inspect
-
import numpy.testing as npt
import numpy as np
from scipy.lib.six import xrange
from scipy import stats
from common_tests import (check_normalization, check_moment, check_mean_expect,
- check_var_expect, check_skew_expect, check_kurt_expect)
+ check_var_expect, check_skew_expect, check_kurt_expect,
+ check_entropy, check_private_entropy, check_edge_support,
+ check_named_args)
DECIMAL_meanvar = 0 # 1 # was 0
@@ -35,7 +35,6 @@
def test_discrete_basic():
for distname, arg in distdiscrete:
distfn = getattr(stats,distname)
- #npt.assert_(stats.dlaplace.rvs(0.8) is not None)
np.random.seed(9765456)
rvs = distfn.rvs(size=2000,*arg)
supp = np.unique(rvs)
@@ -58,6 +57,8 @@ def test_discrete_basic():
yield check_discrete_chisquare, distfn, arg, rvs, alpha, \
distname + ' chisquare'
+ yield check_edge_support, distfn, arg
+
seen = set()
for distname, arg in distdiscrete:
if distname in seen:
@@ -73,10 +74,10 @@ def test_discrete_basic():
yield check_named_args, distfn, k, arg, locscale_defaults, meths
yield check_scale_docstring, distfn
- # compare a generic _entropy w/ distribution-specific implementation,
- # if available
+ # Entropy
+ yield check_entropy, distfn, arg, distname
if distfn.__class__._entropy != stats.rv_discrete._entropy:
- yield check_private_entropy, distfn, arg
+ yield check_private_entropy, distfn, arg, stats.rv_discrete
def test_moments():
@@ -97,18 +98,6 @@ def test_moments():
yield knf(cond, msg)(check_kurt_expect), distfn, arg, m, v, k, distname
-@npt.dec.slow
-def test_discrete_extra():
- for distname, arg in distdiscrete:
- distfn = getattr(stats,distname)
- yield check_ppf_limits, distfn, arg, distname + \
- ' ppf limit test'
- yield check_isf_limits, distfn, arg, distname + \
- ' isf limit test'
- yield check_entropy, distfn, arg, distname + \
- ' entropy nan test'
-
-
@npt.dec.skipif(True)
def test_discrete_private():
# testing private methods mostly for debugging
@@ -204,39 +193,6 @@ def check_oth(distfn, arg, msg):
npt.assert_(distfn.cdf(median_sf + 1, *arg) > 0.5)
npt.assert_equal(distfn.isf(0.5, *arg), distfn.ppf(0.5, *arg))
-# next 3 functions copied from test_continous_extra
-# adjusted
-
-
-def check_ppf_limits(distfn,arg,msg):
- below,low,upp,above = distfn.ppf([-1,0,1,2], *arg)
- # print distfn.name, distfn.a, low, distfn.b, upp
- # print distfn.name,below,low,upp,above
- assert_equal_inf_nan(distfn.a-1,low, msg + 'ppf lower bound')
- assert_equal_inf_nan(distfn.b,upp, msg + 'ppf upper bound')
- npt.assert_(np.isnan(below), msg + 'ppf out of bounds - below')
- npt.assert_(np.isnan(above), msg + 'ppf out of bounds - above')
-
-
-def check_isf_limits(distfn,arg,msg):
- below,low,upp,above = distfn.isf([-1,0,1,2], *arg)
- # print distfn.name, distfn.a, low, distfn.b, upp
- # print distfn.name,below,low,upp,above
- assert_equal_inf_nan(distfn.a-1,upp, msg + 'isf lower bound')
- assert_equal_inf_nan(distfn.b,low, msg + 'isf upper bound')
- npt.assert_(np.isnan(below), msg + 'isf out of bounds - below')
- npt.assert_(np.isnan(above), msg + 'isf out of bounds - above')
-
-
-def assert_equal_inf_nan(v1,v2,msg):
- npt.assert_(not np.isnan(v1))
- if not np.isinf(v1):
- npt.assert_almost_equal(v1, v2, decimal=10, err_msg=msg +
- ' - finite')
- else:
- npt.assert_(np.isinf(v2) or np.isnan(v2),
- msg + ' - infinite, v2=%s' % str(v2))
-
def check_sample_skew_kurt(distfn, arg, sk, ss, msg):
k,s = distfn.stats(moments='ks', *arg)
@@ -244,10 +200,6 @@ def check_sample_skew_kurt(distfn, arg, sk, ss, msg):
check_sample_meanvar, ss, s, msg + 'sample kurtosis test'
-def check_entropy(distfn, arg, msg):
- ent = distfn.entropy(*arg)
- npt.assert_(not np.isnan(ent), msg + 'test Entropy is nan')
-
def check_discrete_chisquare(distfn, arg, rvs, alpha, msg):
"""Perform chisquare test for random sample of a discrete distribution
@@ -306,55 +258,11 @@ def check_discrete_chisquare(distfn, arg, rvs, alpha, msg):
' at arg = %s with pval = %s' % (msg,str(arg),str(pval)))
-def check_named_args(distfn, x, shape_args, defaults, meths):
- """Check calling w/ named arguments."""
- ### This is a copy-paste from test_continuous_basic.py; dedupe?
-
- # check consistency of shapes, numargs and _parse signature
- signature = inspect.getargspec(distfn._parse_args)
- npt.assert_(signature.varargs is None)
- npt.assert_(signature.keywords is None)
- npt.assert_(signature.defaults == defaults)
-
- shape_argnames = signature.args[1:-len(defaults)] # self, a, b, loc=0, scale=1
- if distfn.shapes:
- shapes_ = distfn.shapes.replace(',', ' ').split()
- else:
- shapes_ = ''
- npt.assert_(len(shapes_) == distfn.numargs)
- npt.assert_(len(shapes_) == len(shape_argnames))
-
- # check calling w/ named arguments
- shape_args = list(shape_args)
-
- vals = [meth(x, *shape_args) for meth in meths]
- npt.assert_(np.all(np.isfinite(vals)))
-
- names, a, k = shape_argnames[:], shape_args[:], {}
- while names:
- k.update({names.pop(): a.pop()})
- v = [meth(x, *a, **k) for meth in meths]
- npt.assert_array_equal(vals, v)
- if not 'n' in k.keys():
- # `n` is first parameter of moment(), so can't be used as named arg
- npt.assert_equal(distfn.moment(3, *a, **k),
- distfn.moment(3, *shape_args))
-
- # unknown arguments should not go through:
- k.update({'kaboom': 42})
- npt.assert_raises(TypeError, distfn.cdf, x, **k)
-
-
def check_scale_docstring(distfn):
if distfn.__doc__ is not None:
# Docstrings can be stripped if interpreter is run with -OO
npt.assert_('scale' not in distfn.__doc__)
-def check_private_entropy(distfn, args):
- # compare a generic _entropy with the distribution-specific implementation
- npt.assert_allclose(distfn._entropy(*args),
- stats.rv_discrete._entropy(distfn, *args))
-
if __name__ == "__main__":
npt.run_module_suite()
View
117 scipy/stats/tests/test_distributions.py
@@ -25,19 +25,6 @@
DOCSTRINGS_STRIPPED = sys.flags.optimize > 1
-def kolmogorov_check(diststr, args=(), N=20, significance=0.01):
- qtest = stats.ksoneisf(significance, N)
- cdf = eval('stats.'+diststr+'.cdf')
- dist = eval('stats.'+diststr)
- # Get random numbers
- kwds = {'size':N}
- vals = numpy.sort(dist.rvs(*args, **kwds))
- cdfvals = cdf(vals, *args)
- q = max(abs(cdfvals - np.arange(1.0, N+1)/N))
- assert_(q < qtest, msg="Failed q=%f, bound=%f, alpha=%f" % (q, qtest, significance))
- return
-
-
# generate test cases to test cdf and distribution consistency
dists = ['uniform','norm','lognorm','expon','beta',
'powerlaw','bradford','burr','fisk','cauchy','halfcauchy',
@@ -333,7 +320,7 @@ def test_precision(self):
assert_almost_equal(hgpmf, 0.0010114963068932233, 11)
def test_precision2(self):
- """Test hypergeom precision for large numbers. See #1218."""
+ # Test hypergeom precision for large numbers. See #1218.
# Results compared with those from R.
oranges = 9.9e4
pears = 1.1e5
@@ -541,6 +528,8 @@ def test_rvs(self):
val = stats.dlaplace(1.5).rvs(3)
assert_(isinstance(val, numpy.ndarray))
assert_(val.dtype.char in typecodes['AllInteger'])
+ assert_(stats.dlaplace.rvs(0.8) is not None)
+
def test_stats(self):
# compare the explicit formulas w/ direct summation using pmf
@@ -906,7 +895,7 @@ def check(func, dist, args, alpha):
yield check, func, dist, args, alpha
def test_fix_fit_2args_lognorm(self):
- """Regression test for #1551."""
+ # Regression test for #1551.
np.random.seed(12345)
with np.errstate(all='ignore'):
x = stats.lognorm.rvs(0.25, 0., 20.0, size=20)
@@ -1023,11 +1012,10 @@ def mlefunc(a, b, x):
class TestFrozen(TestCase):
- """Test that a frozen distribution gives the same results as the original object.
-
- Only tested for the normal distribution (with loc and scale specified) and for the
- gamma distribution (with a shape parameter specified).
- """
+ # Test that a frozen distribution gives the same results as the original object.
+ #
+ # Only tested for the normal distribution (with loc and scale specified)
+ # and for the gamma distribution (with a shape parameter specified).
def test_norm(self):
dist = stats.norm
frozen = stats.norm(loc=10.0, scale=3.0)
@@ -1142,12 +1130,10 @@ def test_regression_ticket_1293(self):
class TestExpect(TestCase):
- """Test for expect method.
-
- Uses normal distribution and beta distribution for finite bounds, and
- hypergeom for discrete distribution with finite support
-
- """
+ # Test for expect method.
+ #
+ # Uses normal distribution and beta distribution for finite bounds, and
+ # hypergeom for discrete distribution with finite support
def test_norm(self):
v = stats.norm.expect(lambda x: (x-5)*(x-5), loc=5, scale=2)
assert_almost_equal(v, 4, decimal=14)
@@ -1282,6 +1268,75 @@ def test_nct_inf_moments(self):
assert_equal(k, np.nan)
+class TestRice(TestCase):
+ def test_rice_zero_b(self):
+ # rice distribution should work with b=0, cf gh-2164
+ x = [0.2, 1., 5.]
+ assert_(np.isfinite(stats.rice.pdf(x, b=0.)).all())
+ assert_(np.isfinite(stats.rice.logpdf(x, b=0.)).all())
+ assert_(np.isfinite(stats.rice.cdf(x, b=0.)).all())
+ assert_(np.isfinite(stats.rice.logcdf(x, b=0.)).all())
+
+ q = [0.1, 0.1, 0.5, 0.9]
+ assert_(np.isfinite(stats.rice.ppf(q, b=0.)).all())
+
+ mvsk = stats.rice.stats(0, moments='mvsk')
+ assert_(np.isfinite(mvsk).all())
+
+ # furthermore, pdf is continuous as b\to 0
+ # rice.pdf(x, b\to 0) = x exp(-x^2/2) + O(b^2)
+ # see e.g. Abramovich & Stegun 9.6.7 & 9.6.10
+ b = 1e-8
+ assert_allclose(stats.rice.pdf(x, 0), stats.rice.pdf(x, b),
+ atol=b, rtol=0)
+
+ def test_rice_rvs(self):
+ rvs = stats.rice.rvs
+ assert_equal(rvs(b=3.).size, 1)
+ assert_equal(rvs(b=3., size=(3, 5)).shape, (3, 5))
+
+
+class TestErlang(TestCase):
+ def test_erlang_runtimewarning(self):
+ # erlang should generate a RuntimeWarning if a non-integer
+ # shape parameter is used.
+ with warnings.catch_warnings():
+ warnings.simplefilter("error", RuntimeWarning)
+
+ # The non-integer shape parameter 1.3 should trigger a RuntimeWarning
+ assert_raises(RuntimeWarning,
+ stats.erlang.rvs, 1.3, loc=0, scale=1, size=4)
+
+ # Calling the fit method with `f0` set to an integer should
+ # *not* trigger a RuntimeWarning. It should return the same
+ # values as gamma.fit(...).
+ data = [0.5, 1.0, 2.0, 4.0]
+ result_erlang = stats.erlang.fit(data, f0=1)
+ result_gamma = stats.gamma.fit(data, f0=1)
+ assert_allclose(result_erlang, result_gamma, rtol=1e-3)
+
+
+class TestRdist(TestCase):
+ @dec.slow
+ def test_rdist_cdf_gh1285(self):
+ # check workaround in rdist._cdf for issue gh-1285.
+ distfn = stats.rdist
+ values = [0.001, 0.5, 0.999]
+ assert_almost_equal(distfn.cdf(distfn.ppf(values, 541.0), 541.0),
+ values, decimal=5)
+
+
+def test_540_567():
+ # test for nan returned in tickets 540, 567
+ assert_almost_equal(stats.norm.cdf(-1.7624320982),0.03899815971089126,
+ decimal=10, err_msg='test_540_567')
+ assert_almost_equal(stats.norm.cdf(-1.7624320983),0.038998159702449846,
+ decimal=10, err_msg='test_540_567')
+ assert_almost_equal(stats.norm.cdf(1.38629436112, loc=0.950273420309,
+ scale=0.204423758009),0.98353464004309321,
+ decimal=10, err_msg='test_540_567')
+
+
def test_regression_ticket_1316():
# The following was raising an exception, because _construct_default_doc()
# did not handle the default keyword extradoc=None. See ticket #1316.
@@ -1591,13 +1646,13 @@ def _pdf(self, x, a, b):
return a + b
def _cdf(self, x, a):
- """Different # of shape params from _pdf, to be able to check that
- inspection catches the inconsistency."""
+ # Different # of shape params from _pdf, to be able to check that
+ # inspection catches the inconsistency."""
return 42 * a + x
class _distr6_gen(stats.rv_continuous):
- #Two shape parameters (both _pdf and _cdf defined, consistent shapes.)
+ # Two shape parameters (both _pdf and _cdf defined, consistent shapes.)
def _pdf(self, x, a, b):
return a*x + b
@@ -1606,7 +1661,7 @@ def _cdf(self, x, a, b):
class TestSubclassingExplicitShapes(TestCase):
- """Construct a distribution w/ explicit shapes parameter and test it."""
+ # Construct a distribution w/ explicit shapes parameter and test it.
def test_correct_shapes(self):
dummy_distr = _distr_gen(name='dummy', shapes='a')
@@ -1725,7 +1780,7 @@ def _pdf(self, x):
class TestSubclassingNoShapes(TestCase):
- """Construct a distribution w/o explicit shapes parameter and test it."""
+ # Construct a distribution w/o explicit shapes parameter and test it.
def test_only__pdf(self):
dummy_distr = _distr_gen(name='dummy')
Something went wrong with that request. Please try again.