Creando nuevas distribuciones en scipy.

Estoy tratando de crear una distribución basada en algunos datos que tengo, luego dibujar al azar de esa distribución. Esto es lo que tengo:

from scipy import stats
import numpy

def getDistribution(data):
    kernel = stats.gaussian_kde(data)
    class rv(stats.rv_continuous):
        def _cdf(self, x):
            return kernel.integrate_box_1d(-numpy.Inf, x)
    return rv()

if __name__ == "__main__":
    # pretend this is real data
    data = numpy.concatenate((numpy.random.normal(2,5,100), numpy.random.normal(25,5,100)))
    d = getDistribution(data)

    print d.rvs(size=100) # this usually fails

Creo que esto está haciendo lo que quiero, pero con frecuencia recibo un error (vea a continuación) cuando intento hacerlod.rvs()yd.rvs(100) nunca funciona ¿Estoy haciendo algo mal? ¿Hay una manera más fácil o mejor de hacer esto? Si es un error en Scipy, ¿hay alguna manera de evitarlo?

Finalmente, ¿hay más documentación sobre cómo crear distribuciones personalizadas en algún lugar? Lo mejor que he encontrado es la documentación scipy.stats.rv_continuous, que es bastante espartana y no contiene ejemplos útiles.

El rastreo:

Seguimiento (última llamada más reciente): archivo "testDistributions.py", línea 19, en impresión d.rvs (tamaño = 100) Archivo "/usr/local/lib/python2.6/dist-packages/scipy-0.10.0 -py2.6-linux-x86_64.egg / scipy / stats / distributions.py ", línea 696, en rvs vals = self._rvs (* args) Archivo" /usr/local/lib/python2.6/dist-packages /scipy-0.10.0-py2.6-linux-x86_64.egg/scipy/stats/distributions.py ", línea 1193, en _rvs Y = self._ppf (U, * args) Archivo" / usr / local / lib /python2.6/dist-packages/scipy-0.10.0-py2.6-linux-x86_64.egg/scipy/stats/distributions.py ", línea 1212, en _ppf return self.vecfunc (q, * args) Archivo "/usr/local/lib/python2.6/dist-packages/numpy-1.6.1-py2.6-linux-x86_64.egg/numpy/lib/function_base.py", línea 1862, enllamada theout = self.thefunc (* newargs) Archivo "/usr/local/lib/python2.6/dist-packages/scipy-0.10.0-py2.6-linux-x86_64.egg/scipy/stats/distributions.py" , línea 1158, en _ppf_single_call devolver optim.brentq (self._ppf_to_solve, self.xa, self.xb, args = (q,) + args, xtol = self.xtol) Archivo "/usr/local/lib/python2.6 /dist-packages/scipy-0.10.0-py2.6-linux-x86_64.egg/scipy/optimize/zeros.py ", línea 366, en brentq r = _zeros._brentq (f, a, b, xtol, maxiter , args, full_output, disp) ValueError: f (a) yf (b) deben tener signos diferentes

Editar

Para aquellos curiosos, siguiendo el consejo en la respuesta a continuación, aquí está el código que funciona:

from scipy import stats
import numpy

def getDistribution(data):
    kernel = stats.gaussian_kde(data)
    class rv(stats.rv_continuous):
        def _rvs(self, *x, **y):
            # don't ask me why it's using self._size 
            # nor why I have to cast to int
            return kernel.resample(int(self._size)) 
        def _cdf(self, x):
            return kernel.integrate_box_1d(-numpy.Inf, x)
        def _pdf(self, x):
            return kernel.evaluate(x)
    return rv(name='kdedist', xa=-200, xb=200)

Respuestas a la pregunta(1)

Su respuesta a la pregunta