scipy.stats.

make_distribution#

scipy.stats.make_distribution(dist)[源代码]#

从兼容对象生成一个 UnivariateDistribution

参数可以是 rv_continuous 的实例,也可以是满足如下接口的另一个类的实例。

如果输入是 rv_continuous 的实例,则返回值是一个 ContinuousDistribution 子类;如果输入是 rv_discrete 的实例,则返回一个 DiscreteDistribution 子类。与任何 UnivariateDistribution 的子类一样,在使用前必须实例化(例如,通过将所有形状参数作为关键字参数传递)。一旦实例化,生成的结果对象将具有与 UnivariateDistribution 的任何其他实例相同的接口;例如,scipy.stats.Normalscipy.stats.Binomial

注意

make_distribution 并非与所有 rv_continuous 的实例完美兼容。已知的失败案例包括 levy_stablevonmiseshypergeom、‘nchypergeom_fisher’、‘nchypergeom_wallenius’ 和 poisson_binom。某些分布的某些方法将不支持数组形状参数。

参数:
distrv_continuous

rv_continuousrv_discrete 的实例,或者任何具有以下属性的类的实例

__make_distribution_version__str

包含定义此接口的 SciPy 版本号的字符串。首选接口可能会在未来的 SciPy 版本中发生变化,在这种情况下,对旧接口版本的支持可能会被弃用并最终删除。

parametersdict 或 tuple

如果是一个字典,则每个键都是一个参数的名称,并且对应的值是一个字典或元组。如果该值是一个字典,则它可以具有以下项目,并使用默认值作为不存在的条目。

endpointstuple, default: (-inf, inf)

定义参数域的下限和上限端点的元组;允许的值是浮点数、另一个参数的名称(字符串),或一个可调用对象,该对象接受参数作为仅关键字参数并返回给定参数值的端点的数值。

inclusivetuple of bool, default: (False, False)

一个元组,用于指定端点是否包含在参数域中。

typicaltuple, default: endpoints

定义参数的典型值范围的端点。可用于采样参数值以进行测试。其行为类似于上面的 endpoints 元组,并且应定义一个由 endpoints 给出的域的子区间。

parameters 字典中的键关联的元组值 (a, b) 等价于 {endpoints: (a, b)}

具有多个参数化的自定义分布可以通过将 parameters 属性定义为具有上述结构的字典的元组来定义。在这种情况下,dist 的类还必须定义一个方法 process_parameters,以在不同的参数化之间进行映射。它必须接受来自所有参数化的所有参数作为可选的关键字参数,并返回一个将参数映射到值的字典,并使用所提供的参数化的值填充来自其他参数化的值。参见示例。

supportdict 或 tuple

一个描述分布支持的字典,或一个描述支持端点的元组。此行为与上述参数字典的值完全相同,只是忽略了键 typical

该类**必须**还定义一个 pdf 方法,并且**可以**定义方法 logentropyentropymedianmodelogpdflogcdfcdflogccdfccdfilogcdficdfilogccdficcdfmomentsample。如果已定义,这些方法必须接受分布的参数作为关键字参数,并且还接受 ContinuousDistribution 的相应方法接受的任何仅位置参数。当定义了多个参数化时,这些方法必须接受来自所有参数化的所有参数。moment 方法必须按位置或关键字接受 orderkind 参数,但如果该参数没有可用的公式,则可能返回 None;在这种情况下,该基础架构将回退到默认实现。sample 方法必须按位置或关键字接受 shape,但与同名的公共方法相反,它接收的参数将是输出数组的*完整*形状,即传递给公共方法的形状预先添加到随机变量参数的广播形状。

返回值:
CustomDistributionUnivariateDistribution

dist 对应的 UnivariateDistribution 的子类。初始化器要求将所有形状参数作为关键字参数传递(使用与 rv_continuous/rv_discrete 的实例相同的名称)。

注意

没有呈现 UnivariateDistribution 的文档。有关如何实例化该类的示例,请参见下文(即,将 dist 的所有形状参数作为关键字参数传递给初始化器)。所有方法的文档与 scipy.stats.Normal 的文档相同。使用返回类或其方法的 help 获取更多信息。

示例

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> from scipy import stats
>>> from scipy import special

scipy.stats.loguniform 创建一个 ContinuousDistribution

>>> LogUniform = stats.make_distribution(stats.loguniform)
>>> X = LogUniform(a=1.0, b=3.0)
>>> np.isclose((X + 0.25).median(), stats.loguniform.ppf(0.5, 1, 3, loc=0.25))
np.True_
>>> X.plot()
>>> sample = X.sample(10000, rng=np.random.default_rng())
>>> plt.hist(sample, density=True, bins=30)
>>> plt.legend(('pdf', 'histogram'))
>>> plt.show()
../../_images/scipy-stats-make_distribution-1_00_00.png

创建一个自定义分布。

>>> class MyLogUniform:
...     @property
...     def __make_distribution_version__(self):
...         return "1.16.0"
...
...     @property
...     def parameters(self):
...         return {'a': {'endpoints': (0, np.inf),
...                       'inclusive': (False, False)},
...                 'b': {'endpoints': ('a', np.inf),
...                       'inclusive': (False, False)}}
...
...     @property
...     def support(self):
...         return {'endpoints': ('a', 'b'), 'inclusive': (True, True)}
...
...     def pdf(self, x, a, b):
...         return 1 / (x * (np.log(b)- np.log(a)))
>>>
>>> MyLogUniform = stats.make_distribution(MyLogUniform())
>>> Y = MyLogUniform(a=1.0, b=3.0)
>>> np.isclose(Y.cdf(2.), X.cdf(2.))
np.True_

创建一个具有可变支持的自定义分布。

>>> class MyUniformCube:
...     @property
...     def __make_distribution_version__(self):
...         return "1.16.0"
...
...     @property
...     def parameters(self):
...         return {"a": (-np.inf, np.inf),
...                 "b": {'endpoints':('a', np.inf), 'inclusive':(True, False)}}
...
...     @property
...     def support(self):
...         def left(*, a, b):
...             return a**3
...
...         def right(*, a, b):
...             return b**3
...         return (left, right)
...
...     def pdf(self, x, *, a, b):
...         return 1 / (3*(b - a)*np.cbrt(x)**2)
...
...     def cdf(self, x, *, a, b):
...         return (np.cbrt(x) - a) / (b - a)
>>>
>>> MyUniformCube = stats.make_distribution(MyUniformCube())
>>> X = MyUniformCube(a=-2, b=2)
>>> Y = stats.Uniform(a=-2, b=2)**3
>>> X.support()
(-8.0, 8.0)
>>> np.isclose(X.cdf(2.1), Y.cdf(2.1))
np.True_

创建一个具有多个参数化的自定义分布。在这里,我们创建一个 beta 分布的自定义版本,该版本在均值 mu 和离散参数 nu 方面具有替代参数化。

>>> class MyBeta:
...     @property
...     def __make_distribution_version__(self):
...         return "1.16.0"
...
...     @property
...     def parameters(self):
...         return ({"a": (0, np.inf), "b": (0, np.inf)},
...                 {"mu": (0, 1), "nu": (0, np.inf)})
...
...     def process_parameters(self, a=None, b=None, mu=None, nu=None):
...         if a is not None and b is not None:
...             nu = a + b
...             mu = a / nu
...         else:
...             a = mu * nu
...             b = nu - a
...         return dict(a=a, b=b, mu=mu, nu=nu)
...
...     @property
...     def support(self):
...         return {'endpoints': (0, 1)}
...
...     def pdf(self, x, a, b, mu, nu):
...         return special._ufuncs._beta_pdf(x, a, b)
...
...     def cdf(self, x, a, b, mu, nu):
...         return special.betainc(a, b, x)
>>>
>>> MyBeta = stats.make_distribution(MyBeta())
>>> X = MyBeta(a=2.0, b=2.0)
>>> Y = MyBeta(mu=0.5, nu=4.0)
>>> np.isclose(X.pdf(0.3), Y.pdf(0.3))
np.True_