2010-11-10 26 views
84

In RI può creare l'uscita desiderata facendo:Come creare un grafico della densità in matplotlib?

data = c(rep(1.5, 7), rep(2.5, 2), rep(3.5, 8), 
     rep(4.5, 3), rep(5.5, 1), rep(6.5, 8)) 
plot(density(data, bw=0.5)) 

Density plot in R

In pitone (con matplotlib) più vicino ho trovato era con un semplice istogramma:

import matplotlib.pyplot as plt 
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8 
plt.hist(data, bins=6) 
plt.show() 

Histogram in matplotlib

Ho anche provato the normed=True parameter ma non ho potuto ottenere altro che provare a adattare un gaussiano all'istogramma.

I miei ultimi tentativi erano intorno a scipy.stats e gaussian_kde, seguendo gli esempi sul web, ma fino ad ora non ho avuto esito positivo.

+0

Dai un'occhiata alla 'seaborn' https://stackoverflow.com/a/32803224/1922302 – johk95

risposta

95

Sven ha mostrato come utilizzare la classe gaussian_kde da Scipy, ma si noterà che non assomiglia molto a ciò che è stato generato con R. Questo perché gaussian_kde tenta di dedurre automaticamente la larghezza di banda. È possibile giocare con la larghezza di banda in un modo modificando la funzione covariance_factor della classe gaussian_kde. In primo luogo, qui è quello che si ottiene senza cambiare quella funzione:

alt text

Tuttavia, se uso il seguente codice:

import matplotlib.pyplot as plt 
import numpy as np 
from scipy.stats import gaussian_kde 
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8 
density = gaussian_kde(data) 
xs = np.linspace(0,8,200) 
density.covariance_factor = lambda : .25 
density._compute_covariance() 
plt.plot(xs,density(xs)) 
plt.show() 

ottengo

alt text

che è molto vicino a quello che stai ricevendo da R. Che cosa ho fatto? gaussian_kde utilizza una funzione modificabile, covariance_factor per calcolare la sua larghezza di banda. Prima di modificare la funzione, il valore restituito da covariance_factor per questi dati era circa 0,5. Abbassando questo abbassato la larghezza di banda. Ho dovuto chiamare _compute_covariance dopo aver cambiato quella funzione in modo che tutti i fattori sarebbero stati calcolati correttamente. Non è una corrispondenza esatta con il parametro bw di R, ma si spera che ti aiuti ad andare nella giusta direzione.

+5

@Justin Risposta piacevole (+1) e non voler avviare alcuna guerra di Python contro R flame o altro, ma mi piace il modo in cui R lavora con i dati molto più succintamente di Python e di altri linguaggi. Sono sicuro che Python ha molti punti positivi su R (non sono un utente Python quindi sono così totalmente in grado di commentare) e può essere usato per un sacco di lavoro in più rispetto all'analisi dei dati, ma come una R di lunga data utente dimentico quanto sia succinto un linguaggio per tali compiti finché non emergono esempi come questo. –

+0

qui è una sottoclasse di gaussian_kde che consente di impostare la larghezza di banda come argomento. – user333700

+4

(continua a litigare con commenti di modifica) Ecco una sottoclasse di gaussian_kde che consente di impostare la larghezza di banda come argomento e altri esempi: http://mail.scipy.org/pipermail/scipy-user/2010-January/023877.html e c'è un ticket di miglioramento su http://projects.scipy.org/scipy/ticket/1092. Nota, gaussian_kde è progettato per dati n-dimensionali. – user333700

36

Forse provare qualcosa di simile:

import matplotlib.pyplot as plt 
import numpy 
from scipy import stats 
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8 
density = stats.kde.gaussian_kde(data) 
x = numpy.arange(0., 8, .1) 
plt.plot(x, density(x)) 
plt.show() 

Si può facilmente sostituire gaussian_kde() da una stima diversa densità del kernel.

+1

+1 per l'esempio di lavoro e già vicino all'output desiderato – Unode

+0

Dopo aver provato la maggior parte su questa pagina - grazie. –

83

Cinque anni più tardi, quando I Google "come creare un grafico della densità del kernel usando python", questo thread appare ancora in alto!

Oggi, un modo molto più semplice per farlo è usare seaborn, un pacchetto che offre molte utili funzioni di tracciamento e una buona gestione dello stile.

import numpy as np 
import seaborn as sns 
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8 
sns.set_style('whitegrid') 
sns.kdeplot(np.array(data), bw=0.5) 

enter image description here

+0

Grazie mille ... State cercando qualcosa di simile da giorni ... potete spiegare perché viene dato 'bw = 0.5'? –

+1

@SitzBlogz Il parametro 'bw' sta per larghezza di banda. Stavo cercando di abbinare l'impostazione di OP (vedi il suo primo esempio di codice originale). Per una spiegazione dettagliata di cosa controlli 'bw', vedere https://en.wikipedia.org/wiki/Kernel_density_estimation#Bandwidth_selection.Fondamentalmente controlla quanto liscio vuoi che la trama della densità sia. Più grande è il bw, più liscio sarà. – Xin

+0

Ho un'altra domanda per chiedere che i miei dati siano di natura discreta e sto cercando di tracciare il PDF per questo, dopo aver letto il documento scipy ho capito che PMF = PDF qualche suggerimento su come tracciarlo? –

24

Opzione 1:

Usa pandas trama dataframe (costruito sulla cima di matplotlib):

import pandas as pd 
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8 
pd.DataFrame(data).plot(kind='density') # or pd.Series() 

enter image description here

Opzione 2:

Uso distplot di seaborn:

import seaborn as sns 
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8 
sns.distplot(data, hist=False) 

enter image description here

+3

Per aggiungere il parametro bandwidth: df.plot.density (bw_method = 0.5) – Anake

+0

@Aziz Non sono necessari' panda. DataFrame', può usare 'pandas.Series (data) .plot (kind = 'density')' @Anake, non è necessario impostare df.plot.density come un passaggio separato; puoi semplicemente passare il tuo kwarg 'bw_method' in' pd.Series (data) .plot (kind = 'density', bw_method = 0.5) ' –

+1

@TheRedPea davvero grazie :-) Ho appena aggiornato la mia risposta. –

Problemi correlati