如何得到一个pythonscipy类型的连续有界rv分布对象?

How to obtain a python scipy-type continuous rv distribution object that is bounded?

我想定义一个有界版本的连续随机变量分布(例如,指数分布,但我可能也想使用其他分布)。边界是 0 和 1。我想

  1. 绘制随机变量(由 scipy.stats.rv_continuous.rvs 完成),
  2. 使用 ppf(百分比函数)(由 scipy.stats.rv_continuous.ppf 完成),并且可能
  3. 使用 cdf(累积密度函数)(由 scipy.stats.rv_continuous.cdf 完成)

我能想到的可能方法:

我的感觉是可能有更好、更通用的方法来做到这一点。在那儿?也许与同情?也许通过某种方式获取无界cdf的函数对象并直接修改它?

Python是版本:3.6.2,scipy是版本0.19.1。

如果分布是 scipy.stats 中可用的分布之一,那么您可以使用该分布的 cdf 评估其在两个边界之间的积分。否则,您可以定义 rv_continuous 的 pdf,然后使用其 cdf 来获得此积分。

现在,实际上,您拥有所需 pdf 的有界版本的 pdf,因为您已经在该积分中计算了它的归一化常数。您可以继续将 rv_continuous 与 pdf 的形式加上归一化常数和边界一起使用。


您的代码可能如下所示。变量scale是根据scipy文档设置的。 norm 是指数 pdf 在 [0,1] 上的积分。只考虑了大约 0.49 的概率质量。因此,要生成指数,当截断到 [0,1] 区间时给出质量为 1 我们必须将其 pdf 除以该因子。

Truncated_expon 在文档中定义为 rv_continuous 的子类。通过提供它的 pdf,我们可以(至少对于这样一个简单的积分!)scipy 来计算这个分布的 cdf,从而计算随机样本。

我计算了一次的 cdf 作为支票。

>>> from scipy import stats
>>> lamda = 2/3
>>> scale = 1/lamda
>>> norm = stats.expon.cdf(1, scale=scale)
>>> norm
0.48658288096740798
>>> from math import exp
>>> class Truncated_expon(stats.rv_continuous):
...     def _pdf(self, x, lamda):
...         return lamda*exp(-lamda*x)/0.48658288096740798
... 
>>> e = Truncated_expon(a=0, b=1, shapes='lamda')
>>> e.cdf(1, lamda=lamda)
1.0
>>> e.rvs(size=20, lamda=lamda)
array([ 0.20064067,  0.67646465,  0.89118679,  0.86093035,  0.14334989,
        0.10505598,  0.53488779,  0.11606106,  0.41296616,  0.33650899,
        0.95126415,  0.57481087,  0.04495104,  0.00308469,  0.23585195,
        0.00653972,  0.59400395,  0.34919065,  0.91762547,  0.40098409])