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?

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


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


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 .


"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')

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.