Mister Mak
Mister Mak

Reputation: 294

Adding methods to scipy.stats.rv_continuous, problems with rv_frozen

I would like to add a method to all of the distribution in scipy.stats.rv_continuous. The method would return the cumulative counts, ie the product of an extra parameter nu (the total counts), and the existing cdf function. I tried adding the new method to the rv_continuous class as follows:

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

but get the following error:

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

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

Not sure how to deal with rv_frozen. Any suggestions? Also, not sure if parameters will cause problems.

Upvotes: 0

Views: 1557

Answers (1)

ev-br
ev-br

Reputation: 26090

The immediate issue you're seeing is that rv2.cntsCumul(xx, 3) creates a so-called frozen distribution, which has shapes and loc/scale fixed --- this way, e.g. norm(loc=0, scale=2).pdf(x) is equivalent to norm.pdf(x, loc=0, scale=2) etc. In the source code, see rv_continuous.__call__ etc. Now, a frozen distribution (an rv_frozen instance) creates a fresh instance of the underlying rv_continuous subclass (which is stored as a self.dist attribute of an rv_frozen instance), and that one does not know about your monkey-patching.

Note also that what you are doing does not account for the shape parameters: e.g. gamma has shape a, so that the signature is scipy.stats.gamma.pdf(x, a, loc, scale). loc and scale have default values, but shapes do not.

On a side note, like I said in the comments, what you're doing is, to put it mildly, somewhat non-standard. And certainly very error-prone. If you need several distributions, just subclass their _gen classes or monkey-patch the instances if you really must.

Upvotes: 1

Related Questions