Come tracciare un istogramma usando Matplotlib in Python con un elenco di dati?


100

Sto provando a tracciare un istogramma usando la matplotlib.hist()funzione ma non sono sicuro di come farlo.

Ho una lista

probability = [0.3602150537634409, 0.42028985507246375, 
  0.373117033603708, 0.36813186813186816, 0.32517482517482516, 
  0.4175257731958763, 0.41025641025641024, 0.39408866995073893, 
  0.4143222506393862, 0.34, 0.391025641025641, 0.3130841121495327, 
  0.35398230088495575]

e un elenco di nomi (stringhe).

Come faccio a rendere la probabilità come valore y di ciascuna barra e i nomi come valori x?

Risposte:


168

Se desideri un istogramma, non è necessario allegare alcun "nome" ai valori x, poiché sull'asse x avresti contenitori di dati:

import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
np.random.seed(42)
x = np.random.normal(size=1000)
plt.hist(x, density=True, bins=30)  # `density=False` would make counts
plt.ylabel('Probability')
plt.xlabel('Data');

inserisci qui la descrizione dell'immagine

Puoi rendere il tuo istogramma un po 'più elaborato con PDFlinee, titoli e legenda:

import scipy.stats as st
plt.hist(x, density=True, bins=30, label="Data")
mn, mx = plt.xlim()
plt.xlim(mn, mx)
kde_xs = np.linspace(mn, mx, 301)
kde = st.gaussian_kde(x)
plt.plot(kde_xs, kde.pdf(kde_xs), label="PDF")
plt.legend(loc="upper left")
plt.ylabel('Probability')
plt.xlabel('Data')
plt.title("Histogram");

inserisci qui la descrizione dell'immagine

Tuttavia, se hai un numero limitato di punti dati, come in OP, un grafico a barre avrebbe più senso per rappresentare i tuoi dati (quindi puoi allegare etichette all'asse x):

x = np.arange(3)
plt.bar(x, height=[1,2,3])
plt.xticks(x, ['a','b','c'])

inserisci qui la descrizione dell'immagine


4
Ricorda, nessun punto e virgola alla fine delle righe in Python!
Toad22222

10
@ Toad22222 Questo è un estratto dalla cella del notebook Ipython. Prova a eseguirlo senza punto e virgola e vedi la differenza. Tutti gli snippet di codice che inserisco su SO funzionano perfettamente sul mio computer.
Sergey Bushmanov

2
Se ti stai chiedendo del punto e virgola usato da Sergey, vedi qui e # 16 qui per come il punto e virgola viene usato nelle celle dei taccuini Jupyter (ex taccuini IPython) durante la stampa per sopprimere il testo sull'oggetto del grafico.
Wayne

19

Se non hai ancora installato matplotlib, prova il comando.

> pip install matplotlib

Importazione della libreria

import matplotlib.pyplot as plot

I dati dell'istogramma:

plot.hist(weightList,density=1, bins=20) 
plot.axis([50, 110, 0, 0.06]) 
#axis([xmin,xmax,ymin,ymax])
plot.xlabel('Weight')
plot.ylabel('Probability')

Visualizza istogramma

plot.show()

E l'output è come:

inserisci qui la descrizione dell'immagine


2
La riga plot.axis ([50, 110, 0, 0.06]) 'è inutile per l'esempio. Inoltre, poiché codifica difficilmente l'area del grafico da mostrare, se i tuoi dati non si adattano completamente al suo interno potresti essere confuso sul motivo per cui non vengono visualizzati correttamente.
typhon04

10

Sebbene la domanda sembri richiedere di tracciare un istogramma utilizzando matplotlib.hist() funzione, si può senza dubbio non essere fatto usando lo stesso dato che l'ultima parte della domanda richiede di usare le probabilità date come valori y di barre e nomi dati (stringhe) come il valori x.

Presumo un elenco campione di nomi corrispondenti a determinate probabilità per disegnare la trama. Un semplice grafico a barre serve qui allo scopo per il problema dato. È possibile utilizzare il codice seguente:

import matplotlib.pyplot as plt
probability = [0.3602150537634409, 0.42028985507246375, 
  0.373117033603708, 0.36813186813186816, 0.32517482517482516, 
  0.4175257731958763, 0.41025641025641024, 0.39408866995073893, 
  0.4143222506393862, 0.34, 0.391025641025641, 0.3130841121495327, 
  0.35398230088495575]
names = ['name1', 'name2', 'name3', 'name4', 'name5', 'name6', 'name7', 'name8', 'name9',
'name10', 'name11', 'name12', 'name13'] #sample names
plt.bar(names, probability)
plt.xticks(names)
plt.yticks(probability) #This may be included or excluded as per need
plt.xlabel('Names')
plt.ylabel('Probability')

5

Questa è una vecchia domanda ma nessuna delle risposte precedenti ha affrontato il vero problema, cioè il fatto che il problema sia con la domanda stessa.

Innanzitutto, se le probabilità sono già state calcolate, ovvero i dati aggregati dell'istogramma sono disponibili in modo normalizzato, le probabilità dovrebbero sommarsi a 1. Ovviamente non lo fanno e ciò significa che qualcosa non va qui, con la terminologia o con i dati o nel modo in cui viene posta la domanda.

In secondo luogo, il fatto che le etichette siano fornite (e non gli intervalli) significherebbe normalmente che le probabilità sono di una variabile di risposta categorica - e l'uso di un grafico a barre per tracciare l'istogramma è il migliore (o qualche hacking del metodo hist del pyplot), La risposta di Shayan Shafiq fornisce il codice.

Tuttavia, vedi il problema 1, quelle probabilità non sono corrette e l'uso del grafico a barre in questo caso come "istogramma" sarebbe sbagliato perché non racconta la storia della distribuzione univariata, per qualche motivo (forse le classi si sovrappongono e le osservazioni vengono contate più volte?) e in questo caso tale trama non dovrebbe essere chiamata istogramma.

L'istogramma è per definizione una rappresentazione grafica della distribuzione di variabili univariate (vedere https://www.itl.nist.gov/div898/handbook/eda/section3/histogra.htm , https://en.wikipedia.org/wiki / Istogramma) e viene creato disegnando barre di dimensioni che rappresentano conteggi o frequenze di osservazioni in classi selezionate della variabile di interesse. Se la variabile è misurata su una scala continua, quelle classi sono bin (intervalli). Una parte importante della procedura di creazione dell'istogramma è scegliere come raggruppare (o mantenere senza raggruppare) le categorie di risposte per una variabile categoriale, o come dividere il dominio dei possibili valori in intervalli (dove mettere i confini del bin) per continuo tipo variabile. Tutte le osservazioni dovrebbero essere rappresentate e ciascuna solo una volta nella trama. Ciò significa che la somma delle dimensioni delle barre dovrebbe essere uguale al conteggio totale delle osservazioni (o delle loro aree nel caso delle larghezze variabili, che è un approccio meno comune). Oppure, se l'istogramma è normalizzato, tutte le probabilità devono essere pari a 1.

Se i dati stessi sono un elenco di "probabilità" come risposta, cioè le osservazioni sono valori di probabilità (di qualcosa) per ogni oggetto di studio, la risposta migliore è semplicemente plt.hist(probability)con l'opzione forse di binning, e l'uso di x-label già disponibili è sospettoso.

Quindi il grafico a barre non dovrebbe essere usato come istogramma ma semplicemente

import matplotlib.pyplot as plt
probability = [0.3602150537634409, 0.42028985507246375, 
  0.373117033603708, 0.36813186813186816, 0.32517482517482516, 
  0.4175257731958763, 0.41025641025641024, 0.39408866995073893, 
  0.4143222506393862, 0.34, 0.391025641025641, 0.3130841121495327, 
  0.35398230088495575]
plt.hist(probability)
plt.show()

con i risultati

inserisci qui la descrizione dell'immagine

matplotlib in tal caso arriva di default con i seguenti valori di istogramma

(array([1., 1., 1., 1., 1., 2., 0., 2., 0., 4.]),
 array([0.31308411, 0.32380469, 0.33452526, 0.34524584, 0.35596641,
        0.36668698, 0.37740756, 0.38812813, 0.39884871, 0.40956928,
        0.42028986]),
 <a list of 10 Patch objects>)

il risultato è una tupla di array, il primo array contiene i conteggi delle osservazioni, ovvero ciò che verrà mostrato sull'asse y del grafico (si sommano a 13, numero totale di osservazioni) e il secondo array sono i limiti dell'intervallo per x -asse.

Si può verificare che siano equidistanti,

x = plt.hist(probability)[1]
for left, right in zip(x[:-1], x[1:]):
  print(left, right, right-left)

inserisci qui la descrizione dell'immagine

Oppure, ad esempio per 3 bin (il mio giudizio richiede 13 osservazioni) si otterrebbe questo istogramma

plt.hist(probability, bins=3)

inserisci qui la descrizione dell'immagine

con i dati della trama "dietro le sbarre"

inserisci qui la descrizione dell'immagine

L'autore della domanda deve chiarire qual è il significato dell'elenco di valori "probabilità" - la "probabilità" è solo un nome della variabile di risposta (allora perché ci sono x-etichette pronte per l'istogramma, non ha senso ), oppure i valori della lista sono le probabilità calcolate dai dati (quindi il fatto che non si sommino a 1 non ha senso).


4

Questoèun modo molto complicato per farlo, ma se vuoi creare un istogramma in cui conosci già i valori bin ma non hai i dati di origine, puoi usare la np.random.randintfunzione per generare il numero corretto di valori all'interno dell'intervallo di ciascuno bin per la funzione hist da rappresentare graficamente, ad esempio:

import numpy as np
import matplotlib.pyplot as plt

data = [np.random.randint(0, 9, *desired y value*), np.random.randint(10, 19, *desired y value*), etc..]
plt.hist(data, histtype='stepfilled', bins=[0, 10, etc..])

per quanto riguarda le etichette puoi allineare x tick con i contenitori per ottenere qualcosa del genere:

#The following will align labels to the center of each bar with bin intervals of 10
plt.xticks([5, 15, etc.. ], ['Label 1', 'Label 2', etc.. ])
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.