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.