2012-02-21 13 views
10

Ho un elenco disordinato di nome d che assomiglia:Come plottare cdf in matplotlib in Python?

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

ho semplicemente voglia di tracciare un grafico CDF sulla base di questo elenco utilizzando Matplotlib in Python. Ma non so se c'è una funzione posso usare

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) 

Ora sto usando questo codice, ma il messaggio di errore è:

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

Come quello [mostrato qui] (http://matplotlib.sourceforge.net/examples/pylab_examples/histogram_demo_extended.html) (3a figura)? – chl

+0

@chl sì, qualcosa del genere – manxing

+1

Il tuo errore '__init __() richiede esattamente 1 argomento (2 dato)' deriva dal fatto che il tuo metodo di classe '__init__' dovrebbe prendere in sé' def __init __ (self, data) '. – Hooked

risposta

20

Come accennato, cumsum da numpy funziona bene. Assicurati che i tuoi dati siano PDF corretti (cioè somme su uno), altrimenti il ​​CDF non terminerà all'unità as it should. Ecco un esempio di lavoro minima:

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

Dal momento che stai normalizzando Y (con Y/= (dx * Y) .sum()) per creare un PDF, non dovrebbe anche Y.sum() essere uguale a 1 invece di 100? – fixxxer

+0

@fixxxer 'La normalizzazione del post di Y.sum()' non dovrebbe essere una, perché quel totale cambierebbe se avessimo cambiato la nostra dimensione del passo. Quello che dovrebbe essere uno è l'integrale sul dominio, cioè $ \ int _ {- 2}^{2} f (x) dx = 1 $. _Technically_ la normalizzazione dovrebbe essere 'Y/= np.trapz (Y, X)' ma dal momento che stiamo usando passi equidistanti, sono essenzialmente la stessa cosa. – Hooked

8

La funzione NumPy per calcolare le somme cumulative cumsum può essere utile qui

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') 

Credo che questo avrebbe fatto, per la procedura di riferimento http://www.youtube.com/watch?v=vcoCVVs0fRI

+0

1.] Il codice, così com'è, non funziona nemmeno (cosa è 'c'?). 2.] Ancora più importante, questo NON è il CDF, solo i dati aggiunti a se stesso. Provalo con alcuni dati di esempio per vedere la differenza. – Hooked

8

So di essere in ritardo alla festa. Ma, c'è un modo più semplice se si desidera solo il CDF per la trama e non per i calcoli futuri:

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

A titolo di esempio, il codice relativo a produrre one of these graphs è:

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 dai documenti matplotlib potrebbe essere più utile.

Problemi correlati