HOWTO · Matplotlib
Wie man in Matplotlib ein Histogramm für eine Datenliste zeichnet
Zeichnen Sie ein Histogramm aus einer Python-Liste mit Matplotlibs plt.hist() und passen Sie dann seine Bins, Dichte und Farbe an.
Auf dieser Seite
Um ein Histogramm aus einer Python-Liste zu zeichnen, übergeben Sie die Liste direkt an Matplotlibs Funktion plt.hist(). Die Funktion gruppiert die Werte in Intervalle, die sogenannten Bins, zählt, wie viele Werte in jedes Intervall fallen, und zeichnet einen Balken pro Intervall, sodass die Form des Diagramms zeigt, wie die Werte verteilt sind. Als Eingabe genügt eine einfache Python-Liste; Sie müssen sie nicht zuerst in ein NumPy-Array oder eine pandas-Series umwandeln. Dieser Artikel zeichnet eine Liste mit 21 ganzen Zahlen von 0 bis 9, passt dann die Bins, die Balkenhöhen und die Balkenfarbe an und zeigt schließlich, was bei einer ungültigen Bin-Anzahl und bei einer leeren Liste geschieht.
Ein Histogramm aus einer Liste mit plt.hist() zeichnen
Ohne zusätzliche Argumente teilt plt.hist() den Datenbereich in zehn gleich breite Bins. Das Beispiel erfasst auch die drei Rückgabewerte der Funktion und gibt sie aus, sodass Sie genau sehen, wie die Liste gruppiert wurde:
import matplotlib.pyplot as plt
data = [3, 4, 2, 3, 4, 5, 4, 7, 8, 5, 4, 6, 2, 1, 0, 9, 7, 6, 6, 5, 4]
counts, bin_edges, patches = plt.hist(data)
print("counts:", counts.tolist())
print("bin_edges:", bin_edges.tolist())
plt.xlabel("Value")
plt.ylabel("Count")
plt.title("Histogram of data")
plt.show()
counts: [1.0, 1.0, 2.0, 2.0, 5.0, 3.0, 3.0, 2.0, 1.0, 1.0]
bin_edges: [0.0, 0.9, 1.8, 2.7, 3.6, 4.5, 5.4, 6.3, 7.2, 8.1, 9.0]
plt.hist() gibt drei Werte zurück. counts enthält die Anzahl der Beobachtungen in jedem Bin, bin_edges gibt die Intervallgrenzen an, und patches enthält die Balken-Artists, falls Sie einzelne Balken nachträglich anders gestalten möchten. Die Anzahl der Einträge in counts entspricht der Anzahl der Bins, während bin_edges immer einen Eintrag mehr hat, weil es beide Enden jedes Intervalls markiert. Hier reicht der Datenbereich von 0 bis 9, sodass jeder der zehn Standard-Bins 0,9 breit ist und der höchste Balken das Intervall von 3,6 bis 4,5 ist, das die fünf Vorkommen des Werts 4 enthält. Sie können die Zuweisung auch weglassen und nur plt.hist(data) aufrufen, wenn Sie nur das Diagramm benötigen.
Die Anzahl der Bins oder die Bin-Kanten festlegen
Der Parameter bins steuert, wie die Daten aufgeteilt werden. Eine ganze Zahl wie bins=20 erzeugt entsprechend viele gleich breite Intervalle über den Datenbereich:
import matplotlib.pyplot as plt
data = [3, 4, 2, 3, 4, 5, 4, 7, 8, 5, 4, 6, 2, 1, 0, 9, 7, 6, 6, 5, 4]
counts, bin_edges, patches = plt.hist(data, bins=20)
print("counts:", counts.tolist())
print("number of bins:", len(counts))
plt.xlabel("Value")
plt.ylabel("Count")
plt.title("Histogram with 20 bins")
plt.show()
counts: [1.0, 0.0, 1.0, 0.0, 2.0, 0.0, 2.0, 0.0, 5.0, 0.0, 0.0, 3.0, 0.0, 3.0, 0.0, 2.0, 0.0, 1.0, 0.0, 1.0]
number of bins: 20
Zwanzig Bins sind für diese kleine Liste zu viele: Da die Werte ganze Zahlen sind, bleibt jeder zweite Bin leer, und die Verteilung wirkt unruhiger, als sie ist. Allgemein gilt: Sehr wenige Bins können Strukturen in den Daten verbergen, während viele schmale Bins einen kleinen Datensatz zerklüftet aussehen lassen; wählen Sie also eine Bin-Anzahl, die zu Größe und Streuung Ihrer Liste passt. Anstelle einer ganzen Zahl können Sie auch eine Folge von Kantenwerten wie bins=[0, 2, 4, 6, 8, 10] übergeben, um die Intervallgrenzen selbst festzulegen; die Intervalle dürfen dann unterschiedliche Breiten haben. Wenn die Zähler einen weiten Bereich umfassen, schaltet das optionale Argument log=True die Zählerachse auf eine logarithmische Skala, damit kleinere Balken neben einem hohen Balken sichtbar bleiben. Es ändert nur die Achsenskala, nicht die Eingabewerte oder die Einteilung in Bins.
Wahrscheinlichkeitsdichte statt Anzahlen anzeigen
Standardmäßig sind die Balkenhöhen Anzahlen. Setzen Sie density=True, wenn Sie stattdessen eine Wahrscheinlichkeitsdichte möchten. Matplotlib skaliert die Höhen dann so, dass die Gesamtfläche der Balken 1 beträgt:
import matplotlib.pyplot as plt
data = [3, 4, 2, 3, 4, 5, 4, 7, 8, 5, 4, 6, 2, 1, 0, 9, 7, 6, 6, 5, 4]
counts, bin_edges, patches = plt.hist(data, bins=10, density=True)
print("densities:", [round(d, 4) for d in counts.tolist()])
area = sum(d * (bin_edges[i + 1] - bin_edges[i]) for i, d in enumerate(counts))
print("total area:", round(area, 6))
plt.xlabel("Value")
plt.ylabel("Probability density")
plt.title("Probability histogram of data")
plt.show()
densities: [0.0529, 0.0529, 0.1058, 0.1058, 0.2646, 0.1587, 0.1587, 0.1058, 0.0529, 0.0529]
total area: 1.0
Mit density=True enthält der erste Wert des zurückgegebenen Tupels Dichten statt Anzahlen, und das Beispiel prüft die Normierung, indem es jede Dichte mit ihrer Bin-Breite multipliziert und die Flächen summiert, was genau 1 ergibt. Beachten Sie, dass eine einzelne Balkenhöhe eine Dichte ist, nicht die Wahrscheinlichkeit ihres Intervalls; die Wahrscheinlichkeit eines Intervalls ist seine Balkenfläche, also Höhe mal Breite. Dieser Unterschied ist wichtig, wenn die Bins unterschiedliche Breiten haben, weil ein breiter Balken mehr Wahrscheinlichkeit darstellen kann als ein höherer schmaler. Denken Sie daran, beim Wechsel die Beschriftung der vertikalen Achse anzupassen, wie es das Beispiel tut, damit das Diagramm erklärt, was seine Balkenhöhen bedeuten.
Die Farbe der Balken ändern
Der Parameter color legt die Füllfarbe der Balken fest:
import matplotlib.pyplot as plt
data = [3, 4, 2, 3, 4, 5, 4, 7, 8, 5, 4, 6, 2, 1, 0, 9, 7, 6, 6, 5, 4]
plt.hist(data, bins=10, color="red")
plt.xlabel("Value")
plt.ylabel("Count")
plt.title("Red histogram of data")
plt.show()
Jede Matplotlib-Farbangabe funktioniert, etwa ein Name wie "red", eine Hex-Zeichenfolge wie "#1f77b4" oder ein Ein-Buchstaben-Code. Die Anzeigeoptionen lassen sich in einem Aufruf frei kombinieren, zum Beispiel zeichnet plt.hist(data, bins=20, density=True, color="red") zwanzig rote Balken mit Dichtehöhen. Welche Optionen Sie auch kombinieren: Halten Sie Titel und Achsenbeschriftungen damit im Einklang; ein Dichtediagramm sollte keine Zählerbeschriftung behalten, und ein Diagramm mit zwanzig Bins sollte nicht behaupten, die standardmäßigen zehn zu zeigen.
Ungültige Bin-Anzahl und leere Liste behandeln
Zwei Eingabefehler sollten Sie kennen, bevor sie Sie überraschen. Der erste ist eine Bin-Anzahl, die nicht positiv ist:
import matplotlib.pyplot as plt
data = [3, 4, 2, 3, 4, 5, 4, 7, 8, 5, 4, 6, 2, 1, 0, 9, 7, 6, 6, 5, 4]
plt.hist(data, bins=0)
Traceback (most recent call last):
...
ValueError: `bins` must be positive, when an integer
bins=0 (und jede negative ganze Zahl) löst einen ValueError aus, und es wird nichts gezeichnet. Wenn die Bin-Anzahl aus einer Benutzereingabe oder einer Berechnung stammt, prüfen Sie vor dem Zeichnen, ob sie eine positive ganze Zahl ist, oder übergeben Sie stattdessen eine Folge von Kanten. Der zweite Fall ist eine leere Liste, die sich ganz anders verhält: Sie ist überhaupt kein Fehler.
import matplotlib.pyplot as plt
counts, bin_edges, patches = plt.hist([])
print("counts:", counts.tolist())
print("bin_edges:", [round(e, 2) for e in bin_edges.tolist()])
counts: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
bin_edges: [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
Ohne Daten fällt plt.hist() auf den Standardbereich von 0 bis 1 zurück, gibt zehn Zähler mit dem Wert null zurück und zeichnet ein leeres Achsenpaar, ohne eine Ausnahme auszulösen. Das macht eine leere Liste zu einem stillen Fehlermodus: Wenn Ihre Daten aus einer Datei, einer Abfrage oder einem Filter stammen, prüfen Sie vor dem Zeichnen, ob die Liste nicht leer ist, damit ein fehlender Datensatz nicht zu einem leeren Diagramm wird, das wie ein gültiges Ergebnis aussieht.