Updated distributions.py

master
Per.Andreas.Brodtkorb 14 years ago
parent a2e91f6116
commit 508c74421b

@ -69,10 +69,10 @@ __all__ = [
'weibull_max', 'genlogistic', 'genpareto', 'genexpon', 'genextreme', 'weibull_max', 'genlogistic', 'genpareto', 'genexpon', 'genextreme',
'gamma', 'gengamma', 'genhalflogistic', 'gompertz', 'gumbel_r', 'gamma', 'gengamma', 'genhalflogistic', 'gompertz', 'gumbel_r',
'gumbel_l', 'halfcauchy', 'halflogistic', 'halfnorm', 'hypsecant', 'gumbel_l', 'halfcauchy', 'halflogistic', 'halfnorm', 'hypsecant',
'gausshyper', 'invgamma', 'invnorm', 'invweibull', 'johnsonsb', 'gausshyper', 'invgamma', 'invnorm', 'invgauss', 'invweibull',
'johnsonsu', 'laplace', 'levy', 'levy_l', 'levy_stable', 'johnsonsb', 'johnsonsu', 'laplace', 'levy', 'levy_l',
'logistic', 'loggamma', 'loglaplace', 'lognorm', 'gilbrat', 'levy_stable', 'logistic', 'loggamma', 'loglaplace', 'lognorm',
'maxwell', 'mielke', 'nakagami', 'ncx2', 'ncf', 't', 'gilbrat', 'maxwell', 'mielke', 'nakagami', 'ncx2', 'ncf', 't',
'nct', 'pareto', 'lomax', 'powerlaw', 'powerlognorm', 'powernorm', 'nct', 'pareto', 'lomax', 'powerlaw', 'powerlognorm', 'powernorm',
'rdist', 'rayleigh', 'reciprocal', 'rice', 'recipinvgauss', 'rdist', 'rayleigh', 'reciprocal', 'rice', 'recipinvgauss',
'semicircular', 'triang', 'truncexpon', 'truncnorm', 'semicircular', 'triang', 'truncexpon', 'truncnorm',
@ -352,6 +352,58 @@ class general_cont_ppf(object):
def __call__(self, q, *args): def __call__(self, q, *args):
return self.vecfunc(q, *args) return self.vecfunc(q, *args)
# Frozen RV class
class rv_frozen_old(object):
def __init__(self, dist, *args, **kwds):
self.args = args
self.kwds = kwds
self.dist = dist
def pdf(self, x): #raises AttributeError in frozen discrete distribution
return self.dist.pdf(x, *self.args, **self.kwds)
def cdf(self, x):
return self.dist.cdf(x, *self.args, **self.kwds)
def ppf(self, q):
return self.dist.ppf(q, *self.args, **self.kwds)
def isf(self, q):
return self.dist.isf(q, *self.args, **self.kwds)
def rvs(self, size=None):
kwds = self.kwds.copy()
kwds.update({'size':size})
return self.dist.rvs(*self.args, **kwds)
def sf(self, x):
return self.dist.sf(x, *self.args, **self.kwds)
def stats(self, moments='mv'):
kwds = self.kwds.copy()
kwds.update({'moments':moments})
return self.dist.stats(*self.args, **kwds)
def median(self):
return self.dist.median(*self.args, **self.kwds)
def mean(self):
return self.dist.mean(*self.args, **self.kwds)
def var(self):
return self.dist.var(*self.args, **self.kwds)
def std(self):
return self.dist.std(*self.args, **self.kwds)
def moment(self, n):
return self.dist.moment(n, *self.args, **self.kwds)
def entropy(self):
return self.dist.entropy(*self.args, **self.kwds)
def pmf(self,k):
return self.dist.pmf(k, *self.args, **self.kwds)
def interval(self, alpha):
return self.dist.interval(alpha, *self.args, **self.kwds)
# Frozen RV class # Frozen RV class
class rv_frozen(object): class rv_frozen(object):
''' Frozen continous or discrete 1D Random Variable object (RV) ''' Frozen continous or discrete 1D Random Variable object (RV)
@ -429,7 +481,7 @@ class rv_frozen(object):
def stats(self, moments='mv'): def stats(self, moments='mv'):
''' Some statistics of the given RV''' ''' Some statistics of the given RV'''
kwds = dict(moments=moments) kwds = dict(moments=moments)
return self.dist.stats(*self.par) return self.dist.stats(*self.par, **kwds)
def median(self): def median(self):
return self.dist.median(*self.par) return self.dist.median(*self.par)
def mean(self): def mean(self):
@ -450,47 +502,6 @@ class rv_frozen(object):
return self.dist.interval(alpha, *self.par) return self.dist.interval(alpha, *self.par)
# Frozen RV class
class rv_frozen_old(object):
def __init__(self, dist, *args, **kwds):
self.args = args
self.kwds = kwds
self.dist = dist
def pdf(self,x): #raises AttributeError in frozen discrete distribution
return self.dist.pdf(x,*self.args,**self.kwds)
def cdf(self,x):
return self.dist.cdf(x,*self.args,**self.kwds)
def ppf(self,q):
return self.dist.ppf(q,*self.args,**self.kwds)
def isf(self,q):
return self.dist.isf(q,*self.args,**self.kwds)
def rvs(self, size=None):
kwds = self.kwds
kwds.update({'size':size})
return self.dist.rvs(*self.args,**kwds)
def sf(self,x):
return self.dist.sf(x,*self.args,**self.kwds)
def stats(self,moments='mv'):
kwds = self.kwds
kwds.update({'moments':moments})
return self.dist.stats(*self.args,**kwds)
def median(self):
return self.dist.median(*self.args, **self.kwds)
def mean(self):
return self.dist.mean(*self.args, **self.kwds)
def var(self):
return self.dist.var(*self.args, **self.kwds)
def std(self):
return self.dist.std(*self.args, **self.kwds)
def moment(self,n):
return self.dist.moment(n,*self.args,**self.kwds)
def entropy(self):
return self.dist.entropy(*self.args,**self.kwds)
def pmf(self,k):
return self.dist.pmf(k,*self.args,**self.kwds)
def interval(self,alpha):
return self.dist.interval(alpha, *self.args, **self.kwds)
def stirlerr(n): def stirlerr(n):
@ -638,7 +649,7 @@ def bd0(x, npr):
## pdf -- PDF ## pdf -- PDF
## logpdf -- log PDF (more numerically accurate if possible) ## logpdf -- log PDF (more numerically accurate if possible)
## cdf -- CDF ## cdf -- CDF
## logcdf -- log of CDF ## logcdf -- log of CDF
## sf -- Survival Function (1-CDF) ## sf -- Survival Function (1-CDF)
## logsf --- log of SF ## logsf --- log of SF
## ppf -- Percent Point Function (Inverse of CDF) ## ppf -- Percent Point Function (Inverse of CDF)
@ -670,7 +681,7 @@ def bd0(x, npr):
## ##
## _cdf, _ppf, _rvs, _isf, _sf ## _cdf, _ppf, _rvs, _isf, _sf
## ##
## Rarely would you override _isf and _sf but you could for numerical precision. ## Rarely would you override _isf and _sf but you could for numerical precision.
## ##
## Statistics are computed using numerical integration by default. ## Statistics are computed using numerical integration by default.
## For speed you can redefine this using ## For speed you can redefine this using
@ -881,7 +892,7 @@ class rv_generic(object):
args, loc, scale = self._fix_loc_scale(args, loc, scale) args, loc, scale = self._fix_loc_scale(args, loc, scale)
cond = logical_and(self._argcheck(*args),(scale >= 0)) cond = logical_and(self._argcheck(*args),(scale >= 0))
if not all(cond): if not all(cond):
raise ValueError, "Domain error in arguments." raise ValueError("Domain error in arguments.")
# self._size is total size of all output values # self._size is total size of all output values
self._size = product(size, axis=0) self._size = product(size, axis=0)
@ -1016,7 +1027,7 @@ class rv_generic(object):
""" """
kwds['moments'] = 'v' kwds['moments'] = 'v'
res = math.sqrt(self.stats(*args, **kwds)) res = sqrt(self.stats(*args, **kwds))
return res return res
def interval(self, alpha, *args, **kwds): def interval(self, alpha, *args, **kwds):
@ -1025,7 +1036,7 @@ class rv_generic(object):
Parameters Parameters
---------- ----------
alpha : array-like float in [0,1] alpha : array-like float in [0,1]
Probability that an rv will be drawn from the returned range Probability that an rv will be drawn from the returned range
arg1, arg2, ... : array-like arg1, arg2, ... : array-like
The shape parameter(s) for the distribution (see docstring of the instance The shape parameter(s) for the distribution (see docstring of the instance
object for more information) object for more information)
@ -1037,11 +1048,11 @@ class rv_generic(object):
Returns Returns
------- -------
a, b: array-like (float) a, b: array-like (float)
end-points of range that contain alpha % of the rvs end-points of range that contain alpha % of the rvs
""" """
alpha = arr(alpha) alpha = arr(alpha)
if any((alpha > 1) | (alpha < 0)): if any((alpha > 1) | (alpha < 0)):
raise ValueError, "alpha must be between 0 and 1 inclusive" raise ValueError("alpha must be between 0 and 1 inclusive")
q1 = (1.0-alpha)/2 q1 = (1.0-alpha)/2
q2 = (1.0+alpha)/2 q2 = (1.0+alpha)/2
a = self.ppf(q1, *args, **kwds) a = self.ppf(q1, *args, **kwds)
@ -1297,7 +1308,7 @@ class rv_continuous(rv_generic):
self.expandarr = 1 self.expandarr = 1
if not hasattr(self, 'numargs'): if not hasattr(self,'numargs'):
#allows more general subclassing with *args #allows more general subclassing with *args
cdf_signature = inspect.getargspec(self._cdf.im_func) cdf_signature = inspect.getargspec(self._cdf.im_func)
numargs1 = len(cdf_signature[0]) - 2 numargs1 = len(cdf_signature[0]) - 2
@ -1321,8 +1332,10 @@ class rv_continuous(rv_generic):
# of _mom0_sc, vectorize cannot count the number of arguments correctly. # of _mom0_sc, vectorize cannot count the number of arguments correctly.
if longname is None: if longname is None:
if name[0] in ['aeiouAEIOU']: hstr = "An " if name[0] in ['aeiouAEIOU']:
else: hstr = "A " hstr = "An "
else:
hstr = "A "
longname = hstr + name longname = hstr + name
# generate docstring for subclass instances # generate docstring for subclass instances
@ -1395,7 +1408,7 @@ class rv_continuous(rv_generic):
def _pdf(self,x,*args): def _pdf(self,x,*args):
return derivative(self._cdf,x,dx=1e-5,args=args,order=5) return derivative(self._cdf,x,dx=1e-5,args=args,order=5)
## Could also define any of these ## Could also define any of these
def _logpdf(self, x, *args): def _logpdf(self, x, *args):
return log(self._pdf(x, *args)) return log(self._pdf(x, *args))
@ -1482,8 +1495,8 @@ class rv_continuous(rv_generic):
def logpdf(self, x, *args, **kwds): def logpdf(self, x, *args, **kwds):
""" """
Log of the probability density function at x of the given RV. Log of the probability density function at x of the given RV.
This uses more numerically accurate calculation if available. This uses more numerically accurate calculation if available.
Parameters Parameters
---------- ----------
@ -1520,7 +1533,7 @@ class rv_continuous(rv_generic):
if output.ndim == 0: if output.ndim == 0:
return output[()] return output[()]
return output return output
def cdf(self,x,*args,**kwds): def cdf(self,x,*args,**kwds):
""" """
@ -1963,8 +1976,8 @@ class rv_continuous(rv_generic):
""" """
if (floor(n) != n): if (floor(n) != n):
raise ValueError, "Moment must be an integer." raise ValueError("Moment must be an integer.")
if (n < 0): raise ValueError, "Moment must be positive." if (n < 0): raise ValueError("Moment must be positive.")
if (n == 0): return 1.0 if (n == 0): return 1.0
if (n > 0) and (n < 5): if (n > 0) and (n < 5):
signature = inspect.getargspec(self._stats.im_func) signature = inspect.getargspec(self._stats.im_func)
@ -2092,7 +2105,7 @@ class rv_continuous(rv_generic):
scale = theta[-1] scale = theta[-1]
args = tuple(theta[:-2]) args = tuple(theta[:-2])
except IndexError: except IndexError:
raise ValueError, "Not enough input arguments." raise ValueError("Not enough input arguments.")
if not self._argcheck(*args) or scale <= 0: if not self._argcheck(*args) or scale <= 0:
return inf return inf
x = arr((x-loc) / scale) x = arr((x-loc) / scale)
@ -2256,7 +2269,7 @@ class rv_continuous(rv_generic):
restore = None restore = None
else: else:
if len(fixedn) == len(index): if len(fixedn) == len(index):
raise ValueError, "All parameters fixed. There is nothing to optimize." raise ValueError("All parameters fixed. There is nothing to optimize.")
def restore(args, theta): def restore(args, theta):
# Replace with theta for all numbers not in fixedn # Replace with theta for all numbers not in fixedn
# This allows the non-fixed values to vary, but # This allows the non-fixed values to vary, but
@ -2274,12 +2287,12 @@ class rv_continuous(rv_generic):
return x0, func, restore, args return x0, func, restore, args
def fit(self, data, *args, **kwds): def fit(self, data, *args, **kwds):
""" """
Return MLEs for shape, location, and scale parameters from data. Return MLEs for shape, location, and scale parameters from data.
MLE stands for Maximum Likelihood Estimate. Starting estimates for MLE stands for Maximum Likelihood Estimate. Starting estimates for
the fit are given by input arguments; for any arguments not provided the fit are given by input arguments; for any arguments not provided
with starting estimates, ``self._fitstart(data)`` is called to generate with starting estimates, ``self._fitstart(data)`` is called to generate
such. such.
@ -2290,8 +2303,8 @@ class rv_continuous(rv_generic):
Parameters Parameters
---------- ----------
data : array-like data : array_like
Data to use in calculating the MLEs. Data to use in calculating the MLEs
args : floats, optional args : floats, optional
Starting value(s) for any shape-characterizing arguments (those not Starting value(s) for any shape-characterizing arguments (those not
provided will be determined by a call to ``_fitstart(data)``). provided will be determined by a call to ``_fitstart(data)``).
@ -2305,7 +2318,7 @@ class rv_continuous(rv_generic):
floc : hold location parameter fixed to specified value. floc : hold location parameter fixed to specified value.
fscale : hold scale parameter fixed to specified value fscale : hold scale parameter fixed to specified value.
method : of estimation. Options are method : of estimation. Options are
'ml' : Maximum Likelihood method (default) 'ml' : Maximum Likelihood method (default)
@ -2324,7 +2337,7 @@ class rv_continuous(rv_generic):
""" """
Narg = len(args) Narg = len(args)
if Narg > self.numargs: if Narg > self.numargs:
raise ValueError, "Too many input arguments." raise ValueError("Too many input arguments.")
start = [None]*2 start = [None]*2
if (Narg < self.numargs) or not (kwds.has_key('loc') and if (Narg < self.numargs) or not (kwds.has_key('loc') and
kwds.has_key('scale')): kwds.has_key('scale')):
@ -2340,12 +2353,12 @@ class rv_continuous(rv_generic):
if not callable(optimizer) and isinstance(optimizer, (str, unicode)): if not callable(optimizer) and isinstance(optimizer, (str, unicode)):
if not optimizer.startswith('fmin_'): if not optimizer.startswith('fmin_'):
optimizer = "fmin_"+optimizer optimizer = "fmin_"+optimizer
if optimizer == 'fmin_': if optimizer == 'fmin_':
optimizer = 'fmin' optimizer = 'fmin'
try: try:
optimizer = getattr(optimize, optimizer) optimizer = getattr(optimize, optimizer)
except AttributeError: except AttributeError:
raise ValueError, "%s is not a valid optimizer" % optimizer raise ValueError("%s is not a valid optimizer" % optimizer)
vals = optimizer(func,x0,args=(ravel(data),),disp=0) vals = optimizer(func,x0,args=(ravel(data),),disp=0)
vals = tuple(vals) vals = tuple(vals)
if restore is not None: if restore is not None:
@ -2401,8 +2414,8 @@ class rv_continuous(rv_generic):
@np.deprecate @np.deprecate
def est_loc_scale(self, data, *args): def est_loc_scale(self, data, *args):
"""This function is deprecated, use self.fit_loc_scale(data) instead. """ """This function is deprecated, use self.fit_loc_scale(data) instead. """
return self.fit_loc_scale(data, *args) return self.fit_loc_scale(data, *args)
def freeze(self,*args,**kwds): def freeze(self,*args,**kwds):
return rv_frozen(self,*args,**kwds) return rv_frozen(self,*args,**kwds)
@ -2459,8 +2472,8 @@ class rv_continuous(rv_generic):
else: else:
place(output,cond0,self.vecentropy(*goodargs)+log(scale)) place(output,cond0,self.vecentropy(*goodargs)+log(scale))
return output return output
def expect(self, func=None, args=(), loc=0, scale=1, lb=None, ub=None, def expect(self, func=None, args=(), loc=0, scale=1, lb=None, ub=None,
conditional=False, **kwds): conditional=False, **kwds):
"""calculate expected value of a function with respect to the distribution """calculate expected value of a function with respect to the distribution
@ -2484,11 +2497,11 @@ class rv_continuous(rv_generic):
Returns Returns
------- -------
expected value : float expected value : float
Notes Notes
----- -----
This function has not been checked for it's behavior when the integral is This function has not been checked for it's behavior when the integral is
not finite. The integration behavior is inherited from integrate.quad. not finite. The integration behavior is inherited from integrate.quad.
""" """
if func is None: if func is None:
def fun(x, *args): def fun(x, *args):
@ -2507,7 +2520,7 @@ class rv_continuous(rv_generic):
kwds['args'] = args kwds['args'] = args
return integrate.quad(fun, lb, ub, **kwds)[0] / invfac return integrate.quad(fun, lb, ub, **kwds)[0] / invfac
_EULER = 0.577215664901532860606512090082402431042 # -special.psi(1) _EULER = 0.577215664901532860606512090082402431042 # -special.psi(1)
_ZETA3 = 1.202056903159594285399738161511449990765 # special.zeta(3,1) Apery's constant _ZETA3 = 1.202056903159594285399738161511449990765 # special.zeta(3,1) Apery's constant
@ -2693,7 +2706,7 @@ class beta_gen(rv_continuous):
ku = a**3 - a**2*(2*b-1) + b**2*(b+1) - 2*a*b*(b+2) ku = a**3 - a**2*(2*b-1) + b**2*(b+1) - 2*a*b*(b+2)
ku /= a*b*(a+b+2)*(a+b+3) ku /= a*b*(a+b+2)*(a+b+3)
ku *= 6 ku *= 6
return [sk-g1, ku-g2] return [sk-g1, ku-g2]
a, b = optimize.fsolve(func, (1.0, 1.0)) a, b = optimize.fsolve(func, (1.0, 1.0))
return super(beta_gen, self)._fitstart(data, args=(a,b)) return super(beta_gen, self)._fitstart(data, args=(a,b))
def fit(self, data, *args, **kwds): def fit(self, data, *args, **kwds):
@ -2930,7 +2943,7 @@ class chi2_gen(rv_continuous):
return (df/2.-1)*log(x)-x/2.-gamln(df/2.)-(log(2)*df)/2. return (df/2.-1)*log(x)-x/2.-gamln(df/2.)-(log(2)*df)/2.
## Px = x**(df/2.0-1)*exp(-x/2.0) ## Px = x**(df/2.0-1)*exp(-x/2.0)
## Px /= special.gamma(df/2.0)* 2**(df/2.0) ## Px /= special.gamma(df/2.0)* 2**(df/2.0)
## return log(Px) ## return log(Px)
def _cdf(self, x, df): def _cdf(self, x, df):
return special.chdtr(df, x) return special.chdtr(df, x)
def _sf(self, x, df): def _sf(self, x, df):
@ -4112,30 +4125,67 @@ for x > 0, a > 0.
## Inverse Normal Distribution ## Inverse Normal Distribution
# scale is gamma from DATAPLOT and B from Regress # scale is gamma from DATAPLOT and B from Regress
_invnorm_msg = \
"""The `invnorm` distribution will be renamed to `invgauss` after scipy 0.9"""
class invnorm_gen(rv_continuous): class invnorm_gen(rv_continuous):
def _rvs(self, mu): def _rvs(self, mu):
warnings.warn(_invnorm_msg, DeprecationWarning)
return mtrand.wald(mu, 1.0, size=self._size) return mtrand.wald(mu, 1.0, size=self._size)
def _pdf(self, x, mu): def _pdf(self, x, mu):
warnings.warn(_invnorm_msg, DeprecationWarning)
return 1.0/sqrt(2*pi*x**3.0)*exp(-1.0/(2*x)*((x-mu)/mu)**2) return 1.0/sqrt(2*pi*x**3.0)*exp(-1.0/(2*x)*((x-mu)/mu)**2)
def _logpdf(self, x, mu): def _logpdf(self, x, mu):
warnings.warn(_invnorm_msg, DeprecationWarning)
return -0.5*log(2*pi) - 1.5*log(x) - ((x-mu)/mu)**2/(2*x) return -0.5*log(2*pi) - 1.5*log(x) - ((x-mu)/mu)**2/(2*x)
def _cdf(self, x, mu): def _cdf(self, x, mu):
warnings.warn(_invnorm_msg, DeprecationWarning)
fac = sqrt(1.0/x) fac = sqrt(1.0/x)
C1 = norm.cdf(fac*(x-mu)/mu) C1 = norm.cdf(fac*(x-mu)/mu)
C1 += exp(2.0/mu)*norm.cdf(-fac*(x+mu)/mu) C1 += exp(2.0/mu)*norm.cdf(-fac*(x+mu)/mu)
return C1 return C1
def _stats(self, mu): def _stats(self, mu):
warnings.warn(_invnorm_msg, DeprecationWarning)
return mu, mu**3.0, 3*sqrt(mu), 15*mu return mu, mu**3.0, 3*sqrt(mu), 15*mu
invnorm = invnorm_gen(a=0.0, name='invnorm', longname="An inverse normal", invnorm = invnorm_gen(a=0.0, name='invnorm', longname="An inverse normal",
shapes="mu",extradoc=""" shapes="mu",extradoc="""
Inverse normal distribution Inverse normal distribution
NOTE: `invnorm` will be renamed to `invgauss` after scipy 0.9
invnorm.pdf(x,mu) = 1/sqrt(2*pi*x**3) * exp(-(x-mu)**2/(2*x*mu**2)) invnorm.pdf(x,mu) = 1/sqrt(2*pi*x**3) * exp(-(x-mu)**2/(2*x*mu**2))
for x > 0. for x > 0.
""" """
) )
## Inverse Gaussian Distribution (used to be called 'invnorm'
# scale is gamma from DATAPLOT and B from Regress
class invgauss_gen(rv_continuous):
def _rvs(self, mu):
return mtrand.wald(mu, 1.0, size=self._size)
def _pdf(self, x, mu):
return 1.0/sqrt(2*pi*x**3.0)*exp(-1.0/(2*x)*((x-mu)/mu)**2)
def _logpdf(self, x, mu):
return -0.5*log(2*pi) - 1.5*log(x) - ((x-mu)/mu)**2/(2*x)
def _cdf(self, x, mu):
fac = sqrt(1.0/x)
C1 = norm.cdf(fac*(x-mu)/mu)
C1 += exp(2.0/mu)*norm.cdf(-fac*(x+mu)/mu)
return C1
def _stats(self, mu):
return mu, mu**3.0, 3*sqrt(mu), 15*mu
invgauss = invgauss_gen(a=0.0, name='invgauss', longname="An inverse Gaussian",
shapes="mu",extradoc="""
Inverse Gaussian distribution
invgauss.pdf(x,mu) = 1/sqrt(2*pi*x**3) * exp(-(x-mu)**2/(2*x*mu**2))
for x > 0.
"""
)
## Inverted Weibull ## Inverted Weibull
class invweibull_gen(rv_continuous): class invweibull_gen(rv_continuous):
@ -5009,7 +5059,7 @@ for x > 0, b > 0.
# FIXME: PPF does not work. # FIXME: PPF does not work.
class recipinvgauss_gen(rv_continuous): class recipinvgauss_gen(rv_continuous):
def _rvs(self, mu): #added, taken from invnorm def _rvs(self, mu): #added, taken from invgauss
return 1.0/mtrand.wald(mu, 1.0, size=self._size) return 1.0/mtrand.wald(mu, 1.0, size=self._size)
def _pdf(self, x, mu): def _pdf(self, x, mu):
return 1.0/sqrt(2*pi*x)*exp(-(1-mu*x)**2.0 / (2*x*mu**2.0)) return 1.0/sqrt(2*pi*x)*exp(-(1-mu*x)**2.0 / (2*x*mu**2.0))
@ -5100,9 +5150,9 @@ class truncexpon_gen(rv_continuous):
def _logpdf(self, x, b): def _logpdf(self, x, b):
return -x - log(-expm1(-b)) return -x - log(-expm1(-b))
def _cdf(self, x, b): def _cdf(self, x, b):
return (- expm1(-x)) / (-expm1(-b)) return expm1(-x) / expm1(-b)
def _ppf(self, q, b): def _ppf(self, q, b):
return - log(1 + q*expm1(-b)) return - log1p(q*expm1(-b))
def _munp(self, n, b): def _munp(self, n, b):
#wrong answer with formula, same as in continuous.pdf #wrong answer with formula, same as in continuous.pdf
#return gam(n+1)-special.gammainc(1+n,b) #return gam(n+1)-special.gammainc(1+n,b)
@ -5140,7 +5190,7 @@ class truncnorm_gen(rv_continuous):
self._logdelta = log(self._delta) self._logdelta = log(self._delta)
return (a != b) return (a != b)
# All of these assume that _argcheck is called first # All of these assume that _argcheck is called first
# and no other thread calls _pdf before. # and no other thread calls _pdf before.
def _pdf(self, x, a, b): def _pdf(self, x, a, b):
return _norm_pdf(x) / self._delta return _norm_pdf(x) / self._delta
def _logpdf(self, x, a, b): def _logpdf(self, x, a, b):
@ -5275,7 +5325,7 @@ Von Mises distribution
## Wald distribution (Inverse Normal with shape parameter mu=1.0) ## Wald distribution (Inverse Normal with shape parameter mu=1.0)
class wald_gen(invnorm_gen): class wald_gen(invgauss_gen):
"""A Wald continuous random variable. """A Wald continuous random variable.
%(before_notes)s %(before_notes)s
@ -5290,11 +5340,11 @@ class wald_gen(invnorm_gen):
def _rvs(self): def _rvs(self):
return mtrand.wald(1.0, 1.0, size=self._size) return mtrand.wald(1.0, 1.0, size=self._size)
def _pdf(self, x): def _pdf(self, x):
return invnorm._pdf(x, 1.0) return invgauss._pdf(x, 1.0)
def _logpdf(self, x): def _logpdf(self, x):
return invnorm._logpdf(x, 1.0) return invgauss._logpdf(x, 1.0)
def _cdf(self, x): def _cdf(self, x):
return invnorm._cdf(x, 1.0) return invgauss._cdf(x, 1.0)
def _stats(self): def _stats(self):
return 1.0, 1.0, 3.0, 15.0 return 1.0, 1.0, 3.0, 15.0
wald = wald_gen(a=0.0, name="wald", extradoc=""" wald = wald_gen(a=0.0, name="wald", extradoc="""
@ -5376,7 +5426,7 @@ def entropy(pk,qk=None):
else: else:
qk = arr(qk) qk = arr(qk)
if len(qk) != len(pk): if len(qk) != len(pk):
raise ValueError, "qk and pk must have same length." raise ValueError("qk and pk must have same length.")
qk = 1.0*qk / sum(qk,axis=0) qk = 1.0*qk / sum(qk,axis=0)
# If qk is zero anywhere, then unless pk is zero at those places # If qk is zero anywhere, then unless pk is zero at those places
# too, the relative entropy is infinite. # too, the relative entropy is infinite.
@ -5718,6 +5768,12 @@ class rv_discrete(rv_generic):
self._cdfvec.nin = self.numargs + 1 self._cdfvec.nin = self.numargs + 1
# generate docstring for subclass instances # generate docstring for subclass instances
if longname is None:
if name[0] in ['aeiouAEIOU']:
hstr = "An "
else:
hstr = "A "
longname = hstr + name
if self.__doc__ is None: if self.__doc__ is None:
self._construct_default_doc(longname=longname, extradoc=extradoc) self._construct_default_doc(longname=longname, extradoc=extradoc)
else: else:
@ -5728,6 +5784,8 @@ class rv_discrete(rv_generic):
def _construct_default_doc(self, longname=None, extradoc=None): def _construct_default_doc(self, longname=None, extradoc=None):
"""Construct instance docstring from the rv_discrete template.""" """Construct instance docstring from the rv_discrete template."""
if extradoc is None:
extradoc = ''
if extradoc.startswith('\n\n'): if extradoc.startswith('\n\n'):
extradoc = extradoc[2:] extradoc = extradoc[2:]
self.__doc__ = ''.join(['%s discrete random variable.'%longname, self.__doc__ = ''.join(['%s discrete random variable.'%longname,
@ -6275,8 +6333,8 @@ class rv_discrete(rv_generic):
""" """
if (floor(n) != n): if (floor(n) != n):
raise ValueError, "Moment must be an integer." raise ValueError("Moment must be an integer.")
if (n < 0): raise ValueError, "Moment must be positive." if (n < 0): raise ValueError("Moment must be positive.")
if (n == 0): return 1.0 if (n == 0): return 1.0
if (n > 0) and (n < 5): if (n > 0) and (n < 5):
signature = inspect.getargspec(self._stats.im_func) signature = inspect.getargspec(self._stats.im_func)
@ -6428,7 +6486,7 @@ class rv_discrete(rv_generic):
#handle cases with infinite support #handle cases with infinite support
while (pos <= ub) and (diff > self.moment_tol) and count <= maxcount: while (pos <= ub) and (diff > self.moment_tol) and count <= maxcount:
diff = fun(pos) diff = fun(pos)
tot += diff tot += diff
pos += self.inc pos += self.inc
@ -6437,7 +6495,7 @@ class rv_discrete(rv_generic):
if self.a < 0: #handle case when self.a = -inf if self.a < 0: #handle case when self.a = -inf
diff = 1e100 diff = 1e100
pos = low - self.inc pos = low - self.inc
while (pos >= lb) and (diff > self.moment_tol) and count <= maxcount: while (pos >= lb) and (diff > self.moment_tol) and count <= maxcount:
diff = fun(pos) diff = fun(pos)
tot += diff tot += diff
pos -= self.inc pos -= self.inc
@ -6446,7 +6504,7 @@ class rv_discrete(rv_generic):
# fixme: replace with proper warning # fixme: replace with proper warning
print 'sum did not converge' print 'sum did not converge'
return tot/invfac return tot/invfac
# Binomial # Binomial
@ -6974,7 +7032,7 @@ dlaplace = dlaplace_gen(a=-inf,
Discrete Laplacian distribution. Discrete Laplacian distribution.
dlapacle.pmf(k,a) = tanh(a/2) * exp(-a*abs(k)) dlaplace.pmf(k,a) = tanh(a/2) * exp(-a*abs(k))
for a > 0. for a > 0.
""" """
) )

Loading…
Cancel
Save