Istogramma Matplotlib


107

Quindi ho un piccolo problema. Ho un set di dati in scipy che è già in formato istogramma, quindi ho il centro dei contenitori e il numero di eventi per contenitore. Come posso ora tracciare è come un istogramma. Ho provato solo a farlo

bins, n=hist()

ma non è piaciuto. Qualche consiglio?

Risposte:


239
import matplotlib.pyplot as plt
import numpy as np

mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)
hist, bins = np.histogram(x, bins=50)
width = 0.7 * (bins[1] - bins[0])
center = (bins[:-1] + bins[1:]) / 2
plt.bar(center, hist, align='center', width=width)
plt.show()

inserisci qui la descrizione dell'immagine

Anche l'interfaccia orientata agli oggetti è semplice:

fig, ax = plt.subplots()
ax.bar(center, hist, align='center', width=width)
fig.savefig("1.png")

Se si utilizzano contenitori personalizzati (non costanti), è possibile passare a calcolare le larghezze utilizzando np.diff, passare le larghezze a ax.bare utilizzare ax.set_xticksper etichettare i bordi dei contenitori:

import matplotlib.pyplot as plt
import numpy as np

mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)
bins = [0, 40, 60, 75, 90, 110, 125, 140, 160, 200]
hist, bins = np.histogram(x, bins=bins)
width = np.diff(bins)
center = (bins[:-1] + bins[1:]) / 2

fig, ax = plt.subplots(figsize=(8,3))
ax.bar(center, hist, align='center', width=width)
ax.set_xticks(bins)
fig.savefig("/tmp/out.png")

plt.show()

inserisci qui la descrizione dell'immagine


C'è un modo per far passare i bordi del contenitore all'asse x del grafico a barre?
CMCDragonkai

plt.barIl widthparametro @CMCDragonkai: può accettare un oggetto simile a un array (invece di uno scalare). Quindi potresti usare al width = np.diff(bins)posto di width = 0.7 * (bins[1] - bins[0]).
unutbu

Ma l' widthimpostazione da sola imposta solo la larghezza della barra, giusto? Sto parlando delle etichette dell'asse x (cioè voglio vedere i bordi effettivi del contenitore come etichette sull'asse x). Dovrebbe essere simile a come plt.histfunziona.
CMCDragonkai

2
@CMCDragonkai: potresti usare ax.set_xticksper impostare le xlabels. Ho aggiunto un esempio sopra per mostrare cosa intendo.
unutbu

22

Se non vuoi le barre puoi tracciarlo in questo modo:

import numpy as np
import matplotlib.pyplot as plt

mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)

bins, edges = np.histogram(x, 50, normed=1)
left,right = edges[:-1],edges[1:]
X = np.array([left,right]).T.flatten()
Y = np.array([bins,bins]).T.flatten()

plt.plot(X,Y)
plt.show()

istogramma


6
Puoi anche usare ax.step.
tacaswell

12

So che questo non risponde alla tua domanda, ma finisco sempre su questa pagina, quando cerco la soluzione matplotlib per gli istogrammi, perché il semplice è histogram_demostato rimosso dalla pagina della galleria di esempio di matplotlib.

Ecco una soluzione, che non necessita numpydi essere importata. Importo solo numpy per generare i dati xda tracciare. Si basa sulla funzione histanziché sulla funzione barcome nella risposta di @unutbu.

import numpy as np
mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)

import matplotlib.pyplot as plt
plt.hist(x, bins=50)
plt.savefig('hist.png')

inserisci qui la descrizione dell'immagine

Controlla anche la galleria matplotlib e gli esempi di matplotlib .


"Ecco una soluzione, che non richiede numpy" - la prima riga di codice importa numpy :)
Martin R.

2
@Martin R. Questo è solo per generare i dati da tracciare. Vedere le righe 4-6. Nessun uso di numpy.
tommy.carstensen

6

Se sei disposto a utilizzare pandas:

pandas.DataFrame({'x':hist[1][1:],'y':hist[0]}).plot(x='x',kind='bar')

27
Se intendi suggerire di utilizzarlo pandas, probabilmente dovresti includere un link al loro sito e un altro esempio che spieghi cosa sta succedendo.
tacaswell

0

Penso che questo potrebbe essere utile per qualcuno.

La funzione istogramma di Numpy, con mio fastidio (anche se, apprezzo che ci sia una buona ragione), restituisce i bordi di ogni contenitore, piuttosto che il valore del contenitore. Mentre, questo ha senso per i numeri in virgola mobile, che possono trovarsi all'interno di un intervallo (cioè il valore centrale non è super significativo), questo non è l'output desiderato quando si tratta di valori discreti o interi (0, 1, 2, ecc.) . In particolare, la lunghezza dei bin restituiti da np.histogram non è uguale alla lunghezza dei conteggi / densità.

Per aggirare questo problema, ho usato np.digitize per quantizzare l'input e restituire un numero discreto di bin, insieme a una frazione di conteggi per ogni bin. Puoi facilmente modificare per ottenere il numero intero di conteggi.

def compute_PMF(data)
    import numpy as np
    from collections import Counter
    _, bins = np.histogram(data, bins='auto', range=(data.min(), data.max()), density=False)
    h = Counter(np.digitize(data,bins) - 1)
    weights = np.asarray(list(h.values())) 
    weights = weights / weights.sum()
    values = np.asarray(list(h.keys()))
    return weights, values
####

refs:

[1] https://docs.scipy.org/doc/numpy/reference/generated/numpy.histogram.html

[2] https://docs.scipy.org/doc/numpy/reference/generated/numpy.digitize.html

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.