Histogramm Matplotlib

107

Ich habe also ein kleines Problem. Ich habe einen Datensatz in scipy, der bereits im Histogrammformat vorliegt, also habe ich die Mitte der Bins und die Anzahl der Ereignisse pro Bin. Wie kann ich jetzt als Histogramm zeichnen. Ich habe es einfach versucht

bins, n=hist()

aber das hat es nicht gefallen. Irgendwelche Empfehlungen?

Madtowneast
quelle

Antworten:

238
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()

Geben Sie hier die Bildbeschreibung ein

Die objektorientierte Oberfläche ist ebenfalls unkompliziert:

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

Wenn Sie benutzerdefinierte (nicht konstante) Bins verwenden, können Sie die Breiten mit berechnen np.diff, die Breiten an übergeben ax.barund ax.set_xticksdie Bin-Kanten beschriften:

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

Geben Sie hier die Bildbeschreibung ein

unutbu
quelle
Gibt es eine Möglichkeit, die Bin-Kanten an die x-Achse des Balkendiagramms zu übergeben?
CMCDragonkai
@CMCDragonkai: plt.bar's widthParameter kann ein Array-ähnliches Objekt (anstelle eines Skalars) akzeptieren. Sie könnten also width = np.diff(bins)statt verwenden width = 0.7 * (bins[1] - bins[0]).
Unutbu
Aber die widthEinstellung selbst legt nur die Breite des Balkens fest, oder? Ich spreche von den Beschriftungen der x-Achse (dh ich möchte, dass die tatsächlichen Bin-Kanten Beschriftungen auf der x-Achse sind). Es sollte ähnlich sein wie es plt.histfunktioniert.
CMCDragonkai
2
@CMCDragonkai: Sie können ax.set_xticksdie xlabels festlegen. Ich habe oben ein Beispiel hinzugefügt, um zu zeigen, was ich meine.
Unutbu
22

Wenn Sie keine Balken möchten, können Sie dies folgendermaßen darstellen:

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

Histogramm

Matthias123
quelle
6
Sie können auch verwenden ax.step.
Tacaswell
12

Ich weiß, dass dies Ihre Frage nicht beantwortet, aber ich lande immer auf dieser Seite, wenn ich nach der Matplotlib-Lösung für Histogramme suche, weil das Einfache histogram_demovon der Matplotlib-Beispielgalerieseite entfernt wurde.

Hier ist eine Lösung, die nicht numpyimportiert werden muss. Ich importiere nur numpy, um die xzu zeichnenden Daten zu generieren . Es basiert auf der Funktion histanstelle der Funktion barwie in der Antwort von @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')

Geben Sie hier die Bildbeschreibung ein

Schauen Sie sich auch die Matplotlib-Galerie und die Matplotlib-Beispiele an .

tommy.carstensen
quelle
"Hier ist eine Lösung, für die kein Numpy erforderlich ist" - erste Codezeile importiert Numpy :)
Martin R.
2
@Martin R. Damit werden nur die zu zeichnenden Daten generiert. Siehe Zeilen 4-6. Keine Verwendung von Numpy.
Tommy.carstensen
6

Wenn Sie bereit sind zu verwenden pandas:

pandas.DataFrame({'x':hist[1][1:],'y':hist[0]}).plot(x='x',kind='bar')
Michael Malak
quelle
27
Wenn Sie die Verwendung vorschlagen möchten pandas, sollten Sie wahrscheinlich einen Link zu ihrer Website und ein ausführlicheres Beispiel einfügen, das erklärt, was los ist.
Tacaswell
0

Ich denke, das könnte für jemanden nützlich sein.

Die Histogrammfunktion von Numpy gibt zu meinem Ärger (obwohl ich zu schätzen weiß, dass es einen guten Grund dafür gibt) eher die Ränder jedes Fachs als den Wert des Fachs zurück. Dies ist zwar sinnvoll für Gleitkommazahlen, die innerhalb eines Intervalls liegen können (dh der Mittelwert ist nicht besonders aussagekräftig), dies ist jedoch nicht die gewünschte Ausgabe, wenn es sich um diskrete Werte oder Ganzzahlen (0, 1, 2 usw.) handelt. . Insbesondere ist die Länge der vom np.histogram zurückgegebenen Bins nicht gleich der Länge der Zählungen / Dichte.

Um dies zu umgehen, habe ich np.digitize verwendet, um die Eingabe zu quantisieren und eine diskrete Anzahl von Bins zusammen mit einem Bruchteil der Zählwerte für jeden Bin zurückzugeben. Sie können leicht bearbeiten, um die ganzzahlige Anzahl von Zählungen zu erhalten.

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

Sirgogo
quelle