2012-02-21 17 views
10

Tengo una lista desordenada llamado d que se parece a:Cómo trazar cdf en matplotlib en Python?

[0.0000, 123.9877,0.0000,9870.9876, ...] 

Yo simplemente quiero trazar un gráfico CDF en base a esta lista mediante Matplotlib en Python. Pero no sé si hay alguna función que pueda usar

d = [] 
d_sorted = [] 
for line in fd.readlines(): 
    (addr, videoid, userag, usertp, timeinterval) = line.split() 
    d.append(float(timeinterval)) 

d_sorted = sorted(d) 

class discrete_cdf: 
    def __init__(data): 
     self._data = data # must be sorted 
     self._data_len = float(len(data)) 

    def __call__(point): 
     return (len(self._data[:bisect_left(self._data, point)])/
       self._data_len) 

cdf = discrete_cdf(d_sorted) 
xvalues = range(0, max(d_sorted)) 
yvalues = [cdf(point) for point in xvalues] 
plt.plot(xvalues, yvalues) 

Ahora estoy usando el código, pero el mensaje de error es:

Traceback (most recent call last): 
File "hitratioparea_0117.py", line 43, in <module> 
cdf = discrete_cdf(d_sorted) 
TypeError: __init__() takes exactly 1 argument (2 given) 
+2

Al igual que el [que se muestra aquí] (http://matplotlib.sourceforge.net/examples/pylab_examples/histogram_demo_extended.html) (3ª figura)? – chl

+0

@chl sí, algo así – manxing

+1

Tu error '__init__() toma exactamente 1 argumento (2 dado)' proviene del hecho de que tu método de clase '__init__' debería tomar en sí mismo' def __init __ (self, data) '. – Hooked

Respuesta

20

Como se ha mencionado, cumsum de numpy funciona bien. Asegúrese de que sus datos sean un PDF apropiado (es decir, sumas a uno), de lo contrario, la CDF no terminará en la unidad as it should. Esto es un ejemplo de trabajo mínima:

import numpy as np 
from pylab import * 

# Create some test data 
dx = .01 
X = np.arange(-2,2,dx) 
Y = exp(-X**2) 

# Normalize the data to a proper PDF 
Y /= (dx*Y).sum() 

# Compute the CDF 
CY = np.cumsum(Y*dx) 

# Plot both 
plot(X,Y) 
plot(X,CY,'r--') 

show() 

enter image description here

+0

Dado que están normalizando Y (con Y/= (dx * Y) .sum()) para hacer un PDF, ¿el Y.sum() tampoco debería ser igual a 1 en lugar de 100? – fixxxer

+0

@fixxxer 'Y.sum()' la normalización de la publicación no debería ser una, porque ese total cambiaría si cambiamos el tamaño de nuestro paso. Lo que debería ser uno es la integral sobre el dominio, es decir, $ \ int _ {- 2}^{2} f (x) dx = 1 $. _Tecnicamente_ la normalización debería ser 'Y/= np.trapz (Y, X)' pero como estamos usando pasos equidistantes, son esencialmente lo mismo. – Hooked

8

La función numpy para calcular sumas acumuladas cumsum puede ser útil aquí

In [1]: from numpy import cumsum 
In [2]: cumsum([.2, .2, .2, .2, .2]) 
Out[2]: array([ 0.2, 0.4, 0.6, 0.8, 1. ]) 
-2
import matplotlib.pyplot as plt 
X=sorted(data) 
Y=[] 
l=len(X) 
Y.append(float(1)/l) 
for i in range(2,l+1): 
    Y.append(float(1)/l+Y[i-2]) 
plt.plot(X,Y,color=c,marker='o',label='xyz') 

supongo que esto haría, para el procedimiento se refiere http://www.youtube.com/watch?v=vcoCVVs0fRI

+0

1.] El código, tal como está, ni siquiera funciona (¿qué es 'c'?). 2.] Más importante aún, este NO es el CDF, solo los datos agregados a sí mismo. Pruébalo con algunos datos de muestra para ver la diferencia. – Hooked

8

Sé que llego tarde a la fiesta. Sin embargo, hay una manera más simple si lo que desea es la función de distribución para su trama y no para futuros cálculos:

plt.hist(put_data_here, normed=True, cumulative=True, label='CDF', histtype='step', alpha=0.8, color='k') 

A modo de ejemplo, el código correspondiente para llegar a one of these graphs es:

plt.hist(dataset, bins=bins, normed=True, cumulative=True, label='CDF DATA', histtype='step', alpha=0.55, color='purple') # bins and (lognormal/normal) datasets are pre-defined 

EDIT: This example de los documentos matplotlib puede ser más útil.

Cuestiones relacionadas