首页 > 解决方案 > 向 scipy.stats.rv_continuous 添加方法,rv_frozen 的问题

问题描述

我想为 scipy.stats.rv_continuous 中的所有发行版添加一个方法。该方法将返回累积计数,即额外参数 nu(总计数)与现有 cdf 函数的乘积。我尝试将新方法添加到rv_continuous类中,如下所示:

from scipy.stats import rv_continuous, uniform, gamma

def cntsCumul(self, x, nu): return nu * self.cdf(x)

rv_continuous.cntsCumul = cntsCumul

x = [-0.76, 1.2, 5.67]

for xx in x: print(uniform.cdf(xx)) # OK
for xx in x: print(uniform.cntsCumul(xx, 3)) # Not OK
    
rv1 = uniform()    
for xx in x: print(rv1.cdf(xx)) # OK
for xx in x: print(rv1.cntsCumul(xx, 3)) # Not OK
    
a = 2

for xx in x: print(gamma.cdf(xx, a)) # OK
for xx in x: print(gamma.cntsCumul(xx, a, 3)) # OK

rv2 = gamma(a)
for xx in x: print(rv2.cdf(xx)) # OK
for xx in x: print(rv2.cntsCumul(xx, 3)) # Not OK

但得到以下错误:

---> 14 for xx in x: print(rv1.cntsCumul(xx, 3)) # Not OK
     15 
     16 a = 2

AttributeError: 'rv_frozen' object has no attribute 'cntsCumul'

不知道如何处理rv_frozen。有什么建议么?另外,不确定参数是否会导致问题。

标签: pythonscipyscipy.stats

解决方案


您看到的直接问题是rv2.cntsCumul(xx, 3)创建了一个所谓的冻结分布,它具有固定的形状和位置/比例 --- 这种方式,例如norm(loc=0, scale=2).pdf(x)等价于norm.pdf(x, loc=0, scale=2)等。在源代码中,请参阅rv_continuous.__call__等。现在,冻结分布(rv_frozen实例)创建底层rv_continuous子类的新实例(存储为实例的self.dist属性rv_frozen),并且该实例不知道您的猴子补丁。

另请注意,您正在做的事情不考虑形状参数:例如gamma有 shape a,因此签名是scipy.stats.gamma.pdf(x, a, loc, scale). loc 和 scale 有默认值,但 shape 没有。

在旁注中,就像我在评论中所说的那样,你正在做的是,委婉地说,有点不标准。而且肯定非常容易出错。如果您需要多个发行版,只需对它们的类​​进行子_gen类化,或者如果您确实必须对实例进行猴子补丁。


推荐阅读