Matplotlib-Histogramme in Python — Vollständige Anleitung
Histogramme in Python mit Matplotlib erstellen und anpassen. Bins, Dichte, KDE, kumulativ, gestapelt und Speichern in Dateien.
Die hist()-Funktion von Matplotlib erleichtert die Visualisierung, wie ein Datensatz über einen numerischen Bereich verteilt ist. Dieses Kapitel behandelt alles von einem minimalen ersten Histogramm bis hin zu praktischen Techniken, die Sie in echten Projekten einsetzen werden: die richtige Anzahl von Bins wählen, Dichte statt roher Häufigkeiten darstellen, eine KDE-Kurve überlagern, mehrere Verteilungen vergleichen und das Ergebnis in einer Datei speichern.
Stellen Sie vor dem Einstieg sicher, dass Matplotlib und NumPy installiert sind:
pip install matplotlib numpyWenn Sie neu in der Bibliothek sind, lesen Sie zuerst die Kapitel Matplotlib-Einführung und Erste Schritte.
Was ist ein Histogramm?
Ein Histogramm unterteilt eine kontinuierliche numerische Variable in gleichmäßig beabstandete Intervalle, sogenannte Bins, und zeichnet für jeden Bin einen Balken, dessen Höhe der Anzahl der Beobachtungen in diesem Intervall entspricht. Im Gegensatz zu einem Balkendiagramm, das diskrete Kategorien vergleicht, zeigt ein Histogramm die Form einer Verteilung — ob sie symmetrisch, schief, bimodal ist oder Ausreißer aufweist.
Verwenden Sie ein Histogramm, wenn Sie Fragen wie diese beantworten möchten:
- Wo ist der Großteil der Daten konzentriert?
- Ist die Verteilung annähernd normalverteilt oder schief?
- Gibt es Lücken oder mehrere Peaks (bimodale Daten)?
- Gibt es Ausreißer weit entfernt von der Masse der Daten?
Ein einfaches Histogramm erstellen
Übergeben Sie ein eindimensionales array oder eine Liste an plt.hist(), und Matplotlib wählt automatisch eine Bin-Anzahl:
import matplotlib.pyplot as plt
import numpy as np
# Reproducible example: 1 000 values from a normal distribution
rng = np.random.default_rng(42)
data = rng.normal(loc=0, scale=1, size=1000)
plt.hist(data)
plt.title('Basic Histogram')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.tight_layout()
plt.show()plt.tight_layout() verhindert, dass Achsenbeschriftungen abgeschnitten werden — eine gute Gewohnheit, die man vor jedem show() oder savefig()-Aufruf hinzufügen sollte.
Die Anzahl der Bins wählen
Der Parameter bins ist der wichtigste Einstellknopf für ein Histogramm. Zu wenige Bins verbergen Strukturen; zu viele Bins erzeugen Rauschen.
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
data = rng.normal(loc=0, scale=1, size=1000)
fig, axes = plt.subplots(1, 3, figsize=(12, 4))
for ax, n_bins in zip(axes, [5, 30, 100]):
ax.hist(data, bins=n_bins, color='steelblue', edgecolor='white')
ax.set_title(f'bins={n_bins}')
ax.set_xlabel('Value')
ax.set_ylabel('Frequency')
plt.suptitle('Effect of Bin Count', y=1.02)
plt.tight_layout()
plt.show()Praktische Richtlinien:
- 5–10 Bins — nützlich für sehr kleine Datensätze (n < 50) oder schnelle Übersichten.
- 20–50 Bins — guter Standard für die meisten Datensätze (n = 100–10 000).
- 50–100+ Bins — geeignet für große Datensätze (n > 10 000), bei denen feine Strukturen wichtig sind.
- Übergeben Sie eine Zeichenkettenregel statt einer Zahl:
bins='auto',bins='fd'(Freedman–Diaconis) oderbins='sturges'— Matplotlib delegiert an NumPysnp.histogram_bin_edges().
Sie können auch eine explizite Liste von Bin-Rändern für ungleichmäßige Abstände übergeben:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
data = rng.exponential(scale=2, size=1000)
# Finer bins near 0, coarser bins in the tail
edges = [0, 0.5, 1, 1.5, 2, 3, 4, 6, 8, 12]
plt.hist(data, bins=edges, color='darkorange', edgecolor='white')
plt.title('Custom Bin Edges (Exponential Data)')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.tight_layout()
plt.show()Aussehen anpassen
Farbe, Transparenz und Rand
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
data = rng.normal(loc=5, scale=1.5, size=800)
plt.hist(
data,
bins=30,
color='steelblue',
edgecolor='white', # thin white line between bars
linewidth=0.5,
alpha=0.85, # slight transparency
)
plt.title('Styled Histogram')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.tight_layout()
plt.show()alpha (0 = vollständig transparent, 1 = vollständig undurchsichtig) ist besonders nützlich beim Überlagern mehrerer Histogramme, damit Balken einander nicht verdecken.
Diagrammunrat entfernen
Das Entfernen der oberen und rechten Achsenränder verleiht dem Histogramm ein saubereres Aussehen:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
data = rng.normal(loc=0, scale=1, size=1000)
fig, ax = plt.subplots(figsize=(8, 4))
ax.hist(data, bins=30, color='cornflowerblue', edgecolor='white')
ax.set_title('Clean Histogram')
ax.set_xlabel('Value')
ax.set_ylabel('Frequency')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
plt.tight_layout()
plt.show()Dichte-Histogramme
Standardmäßig zeigt hist() rohe Häufigkeiten auf der y-Achse. Übergeben Sie density=True, um die y-Achse zu normalisieren, sodass die Gesamtfläche aller Balken 1 ergibt. Dadurch wird das Histogramm zu einer Wahrscheinlichkeitsdichteschätzung und ermöglicht den einfachen Vergleich von Datensätzen unterschiedlicher Größen.
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
data = rng.normal(loc=0, scale=1, size=1000)
plt.hist(data, bins=30, density=True, color='mediumseagreen', edgecolor='white')
plt.title('Density Histogram')
plt.xlabel('Value')
plt.ylabel('Probability Density')
plt.tight_layout()
plt.show()Hinweis: Die y-Achsenwerte sind Dichten, keine Wahrscheinlichkeiten. Multiplizieren Sie eine Dichte mit der Bin-Breite, um die Wahrscheinlichkeit für diesen Bin zu erhalten.
Eine KDE-Kurve überlagern
Eine Kerndichteschätzung (KDE) ist eine glatte Kurve, die die zugrundeliegende Wahrscheinlichkeitsverteilung annähert. Das Überlagern auf einem Dichte-Histogramm liefert ein anschauliches Bild der Verteilungsform. Verwenden Sie scipy.stats.gaussian_kde zur Berechnung:
import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import gaussian_kde
rng = np.random.default_rng(42)
data = rng.normal(loc=0, scale=1, size=1000)
fig, ax = plt.subplots(figsize=(8, 4))
# Density histogram
ax.hist(data, bins=30, density=True,
color='steelblue', edgecolor='white', alpha=0.6, label='Histogram')
# KDE curve
xs = np.linspace(data.min(), data.max(), 300)
kde = gaussian_kde(data)
ax.plot(xs, kde(xs), color='navy', linewidth=2, label='KDE')
ax.set_title('Histogram with KDE Overlay')
ax.set_xlabel('Value')
ax.set_ylabel('Probability Density')
ax.legend()
plt.tight_layout()
plt.show()Installieren Sie SciPy, falls es noch nicht verfügbar ist:
pip install scipyMehrere Verteilungen vergleichen
Um zwei oder mehr Verteilungen auf denselben Achsen zu vergleichen, rufen Sie hist() mehrfach auf und verwenden Sie alpha, um die Balken halbtransparent zu halten. Setzen Sie die gleichen bins für beide, damit die Balkenbreiten vergleichbar sind:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
group_a = rng.normal(loc=0, scale=1, size=500)
group_b = rng.normal(loc=2, scale=1.5, size=500)
shared_bins = np.linspace(-5, 8, 40)
plt.hist(group_a, bins=shared_bins, alpha=0.6, color='steelblue', label='Group A')
plt.hist(group_b, bins=shared_bins, alpha=0.6, color='darkorange', label='Group B')
plt.title('Overlapping Histograms')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.legend()
plt.tight_layout()
plt.show()Die Definition von shared_bins über np.linspace() stellt sicher, dass beide Histogramme identische Bin-Ränder verwenden und ihre Balken visuell ausgerichtet sind.
Nebeneinander (gestapelte) Histogramme
Wenn sich Überlappungen schwer lesen lassen, verwenden Sie plt.subplots(), um die Histogramme nebeneinander zu platzieren:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
group_a = rng.normal(loc=0, scale=1, size=500)
group_b = rng.normal(loc=2, scale=1.5, size=500)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 4), sharey=True)
ax1.hist(group_a, bins=30, color='steelblue', edgecolor='white')
ax1.set_title('Group A')
ax1.set_xlabel('Value')
ax1.set_ylabel('Frequency')
ax2.hist(group_b, bins=30, color='darkorange', edgecolor='white')
ax2.set_title('Group B')
ax2.set_xlabel('Value')
plt.suptitle('Side-by-Side Histograms')
plt.tight_layout()
plt.show()sharey=True sperrt beide Teildiagramme auf die gleiche y-Achsenskala, sodass die Balkenhöhen direkt vergleichbar sind. Weitere Layout-Optionen finden Sie im Kapitel Matplotlib-Subplots.
Kumulative Histogramme
Übergeben Sie cumulative=True, um ein Histogramm zu zeichnen, bei dem jeder Balken die Gesamtanzahl der Beobachtungen bis einschließlich dieses Bins darstellt. Dies ist nützlich, um Fragen wie „Welcher Anteil der Werte liegt unterhalb von X?" zu beantworten:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
data = rng.normal(loc=0, scale=1, size=1000)
plt.hist(data, bins=30, cumulative=True, density=True,
color='mediumpurple', edgecolor='white')
plt.title('Cumulative Density Histogram')
plt.xlabel('Value')
plt.ylabel('Cumulative Probability')
plt.tight_layout()
plt.show()In Kombination mit density=True wird das kumulative Histogramm zu einer Stufenfunktions-Approximation der empirischen CDF (kumulativen Verteilungsfunktion). Die y-Achse reicht von 0 bis 1.
Ausrichtung des Histogramms
Übergeben Sie orientation='horizontal', um Balken zu zeichnen, die sich von der y-Achse nach links erstrecken. Dies ist selten die Standardwahl, spiegelt jedoch das Layout der Randverteilungsdiagramme eines Streudiagramms wider:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
data = rng.normal(loc=0, scale=1, size=500)
plt.hist(data, bins=20, orientation='horizontal',
color='tomato', edgecolor='white')
plt.title('Horizontal Histogram')
plt.ylabel('Value')
plt.xlabel('Frequency')
plt.tight_layout()
plt.show()Ein Histogramm in eine Datei speichern
Verwenden Sie plt.savefig() vor plt.show() (oder anstelle davon). Geben Sie das Format über die Dateiendung an:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(42)
data = rng.normal(loc=0, scale=1, size=1000)
plt.hist(data, bins=30, color='steelblue', edgecolor='white')
plt.title('Distribution of Sample Data')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.tight_layout()
plt.savefig('histogram.png', dpi=150) # raster, good for web
plt.savefig('histogram.pdf') # vector, good for print/publication
plt.show()Gängige Formate: png, pdf, svg, eps. Verwenden Sie svg oder pdf, wenn Sie ein skalierbares Bild in Druckqualität benötigen.
hist() Wichtige Parameter — Kurzreferenz
| Parameter | Typ | Beschreibung |
|---|---|---|
bins | int, Liste oder string | Anzahl der Bins, explizite Ränder oder Regelname ('auto', 'fd', 'sturges') |
density | bool | Normalisieren, sodass Gesamtfläche = 1 (Wahrscheinlichkeitsdichte) |
cumulative | bool | Jeder Balken zeigt die kumulative Häufigkeit/Dichte bis zu diesem Bin |
orientation | string | 'vertical' (Standard) oder 'horizontal' |
color | string | Füllfarbe des Balkens |
edgecolor | string | Randfarbe des Balkens; 'white' ergibt einen sauberen Trenner |
alpha | float 0–1 | Transparenz; unter 1 setzen, wenn Histogramme überlagert werden |
label | string | Legendenbeschriftung für dieses Histogramm |
histtype | string | 'bar' (Standard), 'step', 'stepfilled' |
range | (min, max) | Daten auf diesen Bereich vor der Binning-Einteilung begrenzen |
Häufige Fallstricke
- Zufallssamen.
np.random.randn()erzeugt bei jedem Durchlauf unterschiedliche Werte. Verwenden Sienp.random.default_rng(seed)für reproduzierbare Beispiele. densityvsnormed. Der alte Parameternormed=Truewurde in Matplotlib 3.x entfernt. Verwenden Sie immerdensity=True.- Histogramme mit unterschiedlichen Stichprobengrößen vergleichen. Rohe Häufigkeitsbalken sind nicht vergleichbar, wenn die Gruppengrößen abweichen — verwenden Sie
density=True, um beide zu normalisieren. - Diskrete ganzzahlige Daten. Bei ganzen Zahlen (z. B. Würfelwürfe, Umfragebewertungen) setzen Sie Bin-Ränder auf Halbzahlen —
bins=[0.5, 1.5, 2.5, ..., 6.5]— damit jede ganze Zahl eindeutig in genau einen Bin fällt. plt.show()löscht die Figur. Wenn Sieshow()aufrufen und danachsavefig(), erhalten Sie eine leere Datei. Rufen Siesavefig()immer vorshow()auf.
Verwandte Kapitel
- Matplotlib-Einführung — Bibliotheksübersicht und Installation
- Matplotlib: Erste Schritte — Erster Plot Schritt für Schritt
- Matplotlib-Balkendiagramme — diskrete Kategorien vergleichen
- Matplotlib-Streudiagramme — Beziehungen zwischen zwei Variablen
- Matplotlib-Kreisdiagramme — Teil-zu-Ganzes-Verhältnisse
- Matplotlib-Beschriftungen — Achsenbeschriftungen, Titel und Anmerkungen
- Matplotlib-Subplots — mehrere Diagramme in einer Figur
- Datenverteilung — statistischer Hintergrund zu Verteilungen