Search code examples
pythonrandomnumpyscipypoisson

Python/Numpy/Scipy: Draw Poisson random values with different lambda


My problem is to extract in the most efficient way N Poisson random values (RV) each with a different mean/rate Lam. Basically the size(RV) == size(Lam).

Here it is a naive (very slow) implementation:

import numpy as NP

def multi_rate_poisson(Lam):
    rv = NP.zeros(NP.size(Lam))
    for i,lam in enumerate(Lam):
        rv[i] = NP.random.poisson(lam=lam, size=1)
    return rv

That, on my laptop, with 1e6 samples gives:

Lam = NP.random.rand(1e6) + 1
timeit multi_poisson(Lam)
1 loops, best of 3: 4.82 s per loop

Is it possible to improve from this?


Solution

  • Although the docstrings don't document this functionality, the source indicates it is possible to pass an array to the numpy.random.poisson function.

    >>> import numpy
    >>> # 1 dimension array of 1M random var's uniformly distributed between 1 and 2
    >>> numpyarray = numpy.random.rand(1e6) + 1 
    >>> # pass to poisson
    >>> poissonarray = numpy.random.poisson(lam=numpyarray)
    >>> poissonarray
    array([4, 2, 3, ..., 1, 0, 0])
    

    The poisson random variable returns discrete multiples of one, and approximates a bell curve as lambda grows beyond one.

    >>> import matplotlib.pyplot
    >>> count, bins, ignored = matplotlib.pyplot.hist(
                numpy.random.poisson(
                        lam=numpy.random.rand(1e6) + 10), 
                        14, normed=True)
    >>> matplotlib.pyplot.show()
    

    This method of passing the array to the poisson generator appears to be quite efficient.

    >>> timeit.Timer("numpy.random.poisson(lam=numpy.random.rand(1e6) + 1)",
                     'import numpy').repeat(3,1)
    [0.13525915145874023, 0.12136101722717285, 0.12127304077148438]