Matplotlib Histogram: Der vollständige Leitfaden zu plt.hist() in Python
Updated on
Sie haben einen Datensatz mit Tausenden von numerischen Werten -- Alter, Testergebnisse, Antwortzeiten, Sensordaten -- und Sie müssen verstehen, wie diese Werte verteilt sind. Sind sie um einen zentralen Punkt gruppiert? Zu einem Ende hin verzerrt? Folgen sie einer Normalverteilung? Ein Streudiagramm hilft hier nicht weiter. Ein Balkendiagramm ist für Kategorien gedacht, nicht für kontinuierliche Daten. Was Sie brauchen, ist ein Histogramm, und in Python ist matplotlib.pyplot.hist() der Standardweg, um eines zu erstellen.
Das Problem ist, dass plt.hist() über ein Dutzend Parameter hat und die Standardausgabe oft schlicht oder irreführend aussieht. Die Wahl der falschen Anzahl von Bins kann wichtige Muster in Ihren Daten verbergen. Der Vergleich mehrerer Verteilungen in einem Diagramm erfordert die Kenntnis der richtigen Kombination von Optionen. Dieser Leitfaden behandelt jeden Parameter, der wichtig ist, mit funktionierenden Codebeispielen, die Sie direkt in Ihr Notebook oder Skript kopieren können.
Was ist ein Histogramm und wann sollten Sie eines verwenden?
Ein Histogramm unterteilt einen Bereich numerischer Werte in gleichbreite Intervalle, sogenannte Bins, und zählt, wie viele Datenpunkte in jeden Bin fallen. Die x-Achse zeigt den Wertebereich, und die y-Achse zeigt die Häufigkeit (Anzahl) oder Dichte für jeden Bin. Im Gegensatz zu einem Balkendiagramm, das kategoriale Daten darstellt, repräsentiert ein Histogramm die Verteilung kontinuierlicher numerischer Daten.
Verwenden Sie ein Histogramm, wenn Sie:
- Die Form einer Verteilung sehen müssen (normal, schief, bimodal, gleichmäßig)
- Ausreißer oder Lücken in Daten identifizieren möchten
- Die Streuung von Werten über Gruppen hinweg vergleichen möchten
- Datentransformationen vor der Modellierung entscheiden müssen
Grundlegende plt.hist()-Syntax
Das einfachste Histogramm benötigt nur ein Argument: das Datenarray.
import matplotlib.pyplot as plt
import numpy as np
# Generate 1000 normally distributed values
np.random.seed(42)
data = np.random.normal(loc=50, scale=15, size=1000)
plt.hist(data)
plt.title('Basic Histogram')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.show()Standardmäßig unterteilt matplotlib die Daten in 10 Bins. Die Funktion gibt drei Objekte zurück: die Bin-Zählungen, die Bin-Kanten und die Patch-Objekte (die gezeichneten Rechtecke). Wir werden diese Rückgabewerte später im Detail behandeln.
Vollständige Signatur
plt.hist(x, bins=None, range=None, density=False, weights=None,
cumulative=False, bottom=None, histtype='bar', align='mid',
orientation='vertical', rwidth=None, log=False, color=None,
label=None, stacked=False, edgecolor=None, alpha=None)Bins steuern
Der bins-Parameter ist die wichtigste Einstellung in einem Histogramm. Zu wenige Bins verbergen Muster. Zu viele Bins erzeugen Rauschen.
Eine feste Anzahl von Bins festlegen
fig, axes = plt.subplots(1, 3, figsize=(14, 4))
axes[0].hist(data, bins=5, edgecolor='black')
axes[0].set_title('5 Bins')
axes[1].hist(data, bins=30, edgecolor='black')
axes[1].set_title('30 Bins')
axes[2].hist(data, bins=100, edgecolor='black')
axes[2].set_title('100 Bins')
plt.tight_layout()
plt.show()Mit 5 Bins sehen Sie nur eine grobe Form. Mit 100 Bins führen kleine Stichprobengrößen pro Bin zu visuellem Rauschen. Für diesen Datensatz von 1.000 Punkten ergibt 30 Bins ein klares Bild der Normalverteilung.
Benutzerdefinierte Bin-Kanten
Übergeben Sie eine Sequenz an bins, um exakte Grenzen zu definieren:
custom_edges = [0, 20, 35, 50, 65, 80, 100]
plt.hist(data, bins=custom_edges, edgecolor='black', color='steelblue')
plt.title('Histogram with Custom Bin Edges')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.show()Dies ist nützlich, wenn Ihre Daten bedeutungsvolle Schwellenwerte haben -- Buchstabennoten, Altersgruppen oder Leistungsstufen.
Automatische Bin-Algorithmen
Matplotlib unterstützt mehrere Algorithmen, die die optimale Anzahl von Bins basierend auf Dateneigenschaften berechnen:
| Algorithmus | bins=-Wert | Methode | Geeignet für |
|---|---|---|---|
| Sturges | 'sturges' | 1 + log2(n) | Kleine, annähernd normalverteilte Datensätze |
| Scott | 'scott' | Basierend auf Standardabweichung und n | Normale oder nahezu normale Daten |
| Freedman-Diaconis | 'fd' | Basierend auf IQR und n | Robust gegenüber Ausreißern |
| Quadratwurzel | 'sqrt' | sqrt(n) | Schnelle grobe Schätzung |
| Auto | 'auto' | Maximum von Sturges und FD | Allgemeiner Standard |
fig, axes = plt.subplots(1, 3, figsize=(14, 4))
for ax, method in zip(axes, ['sturges', 'scott', 'fd']):
ax.hist(data, bins=method, edgecolor='black', color='#4C72B0')
ax.set_title(f'bins="{method}"')
plt.tight_layout()
plt.show()Für die meisten Fälle ist bins='auto' ein solider Ausgangspunkt. Wechseln Sie zu 'fd', wenn Ihre Daten Ausreißer enthalten, da es den Interquartilsabstand anstelle der Standardabweichung verwendet.
Normalisierte und Dichte-Histogramme
Standardmäßig zeigt die y-Achse Rohzählungen. Setzen Sie density=True, um das Histogramm so zu normalisieren, dass die Gesamtfläche unter den Balken gleich 1 ist. Dies konvertiert die y-Achse von Häufigkeit zu Wahrscheinlichkeitsdichte.
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
axes[0].hist(data, bins=30, edgecolor='black', color='#55A868')
axes[0].set_title('Frequency (default)')
axes[0].set_ylabel('Count')
axes[1].hist(data, bins=30, edgecolor='black', color='#C44E52', density=True)
axes[1].set_title('Density (density=True)')
axes[1].set_ylabel('Probability Density')
plt.tight_layout()
plt.show()Dichtenormalisierung ist unerlässlich, wenn Sie eine theoretische Verteilungskurve überlagern oder Datensätze unterschiedlicher Größe vergleichen möchten:
from scipy import stats
plt.hist(data, bins=30, density=True, edgecolor='black', color='#55A868', alpha=0.7)
# Overlay the theoretical normal curve
x_range = np.linspace(data.min(), data.max(), 200)
plt.plot(x_range, stats.norm.pdf(x_range, loc=50, scale=15), 'r-', linewidth=2, label='Normal PDF')
plt.legend()
plt.title('Density Histogram with Normal Curve Overlay')
plt.show()Erscheinungsbild anpassen
Farbe, Kantenfarbe und Transparenz
plt.hist(data, bins=30, color='#4C72B0', edgecolor='white', alpha=0.85)
plt.title('Styled Histogram')
plt.xlabel('Value')
plt.ylabel('Frequency')
plt.show()Histogramm-Typen
Der Parameter histtype ändert den visuellen Stil:
histtype-Wert | Beschreibung |
|---|---|
'bar' | Traditionelle gefüllte Balken (Standard) |
'barstacked' | Gestapelte Balken für mehrere Datensätze |
'step' | Ungefüllter Linienumriss |
'stepfilled' | Gefüllte Fläche mit Stufenumriss |
fig, axes = plt.subplots(2, 2, figsize=(10, 8))
types = ['bar', 'barstacked', 'step', 'stepfilled']
for ax, ht in zip(axes.flat, types):
ax.hist(data, bins=30, histtype=ht, edgecolor='black', color='#4C72B0')
ax.set_title(f'histtype="{ht}"')
plt.tight_layout()
plt.show()Der Typ 'step' ist besonders nützlich beim Überlagern mehrerer Verteilungen, da ungefüllte Umrisse sich nicht gegenseitig verdecken.
Mehrere Histogramme in einem Diagramm
Überlappende Histogramme
Verwenden Sie alpha (Transparenz), um zwei oder mehr Verteilungen zu überlagern:
np.random.seed(42)
group_a = np.random.normal(loc=50, scale=10, size=800)
group_b = np.random.normal(loc=65, scale=12, size=800)
plt.hist(group_a, bins=30, alpha=0.6, color='#4C72B0', edgecolor='black', label='Group A')
plt.hist(group_b, bins=30, alpha=0.6, color='#C44E52', edgecolor='black', label='Group B')
plt.legend()
plt.title('Overlapping Histograms')
plt.xlabel('Score')
plt.ylabel('Frequency')
plt.show()Nebeneinander liegende Histogramme
Übergeben Sie eine Liste von Arrays, um sie mit gruppierten Balken darzustellen:
plt.hist([group_a, group_b], bins=20, color=['#4C72B0', '#C44E52'],
edgecolor='black', label=['Group A', 'Group B'])
plt.legend()
plt.title('Side-by-Side Histograms')
plt.xlabel('Score')
plt.ylabel('Frequency')
plt.show()Wenn Sie eine Liste von Arrays übergeben, platziert matplotlib die Balken für jeden Datensatz nebeneinander innerhalb jedes Bins.
Gestapelte Histogramme
Setzen Sie stacked=True, um einen Datensatz auf einen anderen zu stapeln. Dies zeigt sowohl die einzelnen Verteilungen als auch deren kombinierte Summe.
np.random.seed(42)
freshmen = np.random.normal(loc=68, scale=8, size=500)
sophomores = np.random.normal(loc=72, scale=7, size=400)
juniors = np.random.normal(loc=75, scale=6, size=300)
plt.hist([freshmen, sophomores, juniors], bins=25, stacked=True,
color=['#4C72B0', '#55A868', '#C44E52'], edgecolor='black',
label=['Freshmen', 'Sophomores', 'Juniors'])
plt.legend()
plt.title('Stacked Histogram: Exam Scores by Class Year')
plt.xlabel('Score')
plt.ylabel('Frequency')
plt.show()Gestapelte Histogramme funktionieren gut, wenn Sie zeigen möchten, wie Untergruppen zu einer Gesamtverteilung beitragen. Allerdings werden sie mit mehr als drei oder vier Gruppen schwer lesbar.
Kumulative Histogramme
Setzen Sie cumulative=True, um zu zeigen, wie sich Werte von links nach rechts akkumulieren. Der letzte Balken erreicht die Gesamtzahl (oder 1,0, wenn density=True).
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
axes[0].hist(data, bins=30, cumulative=True, edgecolor='black', color='#DD8452')
axes[0].set_title('Cumulative Histogram (Count)')
axes[0].set_ylabel('Cumulative Count')
axes[1].hist(data, bins=30, cumulative=True, density=True, edgecolor='black', color='#8172B3')
axes[1].set_title('Cumulative Histogram (Density)')
axes[1].set_ylabel('Cumulative Probability')
plt.tight_layout()
plt.show()Kumulative Histogramme sind nützlich, um Fragen zu beantworten wie "Welcher Prozentsatz der Werte liegt unter 60?", indem man direkt von der y-Achse abliest.
Horizontale Histogramme
Setzen Sie orientation='horizontal', um die Achsen zu tauschen. Dies ist hilfreich, wenn Wertebeschriftungen lang sind oder wenn Sie das Histogramm neben einem anderen vertikalen Diagramm platzieren möchten.
plt.hist(data, bins=30, orientation='horizontal', color='#64B5CD', edgecolor='black')
plt.title('Horizontal Histogram')
plt.xlabel('Frequency')
plt.ylabel('Value')
plt.show()Rückgabewerte von plt.hist()
plt.hist() gibt drei Werte zurück, die Ihnen programmatischen Zugriff auf die Histogrammdaten geben:
n, bin_edges, patches = plt.hist(data, bins=20, edgecolor='black', color='#4C72B0')
plt.show()
print(f"Bin counts (n): shape = {n.shape}, first 5 = {n[:5]}")
print(f"Bin edges: shape = {bin_edges.shape}, first 5 = {bin_edges[:5]}")
print(f"Patches: {len(patches)} Rectangle objects")| Rückgabewert | Typ | Beschreibung |
|---|---|---|
n | ndarray | Anzahl (oder Dichte) für jeden Bin |
bin_edges | ndarray | Kantenwerte für jeden Bin (Länge = len(n) + 1) |
patches | Liste von Rectangles | Die matplotlib-Patch-Objekte für jeden Balken |
Sie können patches verwenden, um einzelne Balken basierend auf ihrer Höhe oder Position einzufärben:
n, bin_edges, patches = plt.hist(data, bins=30, edgecolor='black')
# Color bars based on height
for count, patch in zip(n, patches):
if count > 50:
patch.set_facecolor('#C44E52')
else:
patch.set_facecolor('#4C72B0')
plt.title('Conditional Bar Coloring')
plt.show()Referenz häufiger plt.hist()-Parameter
| Parameter | Typ | Beschreibung | Standard |
|---|---|---|---|
x | array-like | Eingabedaten | Erforderlich |
bins | int, Sequenz oder str | Anzahl der Bins, Bin-Kanten oder Algorithmusname | 10 |
range | tuple | Unterer und oberer Bereich der Bins | (x.min(), x.max()) |
density | bool | Normalisieren, sodass die Fläche gleich 1 ist | False |
weights | array-like | Gewichtung für jeden Datenpunkt | None |
cumulative | bool | Kumulatives Histogramm berechnen | False |
histtype | str | 'bar', 'barstacked', 'step', 'stepfilled' | 'bar' |
orientation | str | 'vertical' oder 'horizontal' | 'vertical' |
color | color oder Liste | Balkenfarbe(n) | None |
edgecolor | color | Kantenfarbe der Balken | None |
alpha | float | Transparenz (0 bis 1) | None |
label | str | Beschriftung für die Legende | None |
stacked | bool | Mehrere Datensätze stapeln | False |
log | bool | Logarithmische y-Achse | False |
rwidth | float | Relative Breite der Balken (0 bis 1) | None |
bottom | array-like oder Skalar | Basislinie für jeden Balken | 0 |
plt.hist() vs. sns.histplot(): Wann welches verwenden
Wenn Sie seaborn neben matplotlib verwenden, fragen Sie sich vielleicht, welche Histogrammfunktion Sie verwenden sollten. Hier ist ein direkter Vergleich:
| Feature | plt.hist() | sns.histplot() |
|---|---|---|
| Bibliothek | matplotlib | seaborn |
| Eingabetypen | Array, Liste, Series | Array, Series, DataFrame-Spalte |
| KDE-Überlagerung | Manuell (scipy benötigt) | Eingebaut (kde=True) |
| Standard-Styling | Minimal | Publikationsreif |
| Mehrere Gruppen | Liste von Arrays übergeben | hue-Parameter |
| Statistik-Optionen | Anzahl, Dichte | Anzahl, Dichte, Häufigkeit, Wahrscheinlichkeit, Prozent |
| Bin-Algorithmen | sturges, scott, fd, sqrt, auto | auto, fd, doane, scott, stone, rice, sturges, sqrt |
| Log-Skala | log=True | log_scale=True |
| Kategoriale Achse | Nicht unterstützt | Unterstützt über hue |
| Leistung (große Daten) | Schneller | Etwas langsamer |
| Anpassungstiefe | Vollständige matplotlib-API | Seaborn + matplotlib-API |
Verwenden Sie plt.hist(), wenn Sie volle Kontrolle über jedes visuelle Element benötigen, wenn Sie mit Subplots arbeiten oder wenn seaborn nicht verfügbar ist. Verwenden Sie sns.histplot(), wenn Sie KDE-Überlagerungen, sauberere Standardstile wünschen oder Daten mit minimalem Code nach einer kategorialen Variable aufteilen müssen.
Erstellen Sie interaktive Histogramme mit PyGWalker
Statische Histogramme sind großartig für Berichte und Skripte, aber bei der explorativen Datenanalyse müssen Sie oft Bins ändern, Teilmengen filtern und schnell zwischen Diagrammtypen wechseln. PyGWalker (opens in a new tab) ist eine Open-Source-Python-Bibliothek, die jeden pandas- oder polars-DataFrame in eine interaktive Drag-and-Drop-Visualisierungsoberfläche direkt im Jupyter Notebook verwandelt -- kein Frontend-Code erforderlich.
pip install pygwalkerimport pandas as pd
import pygwalker as pyg
# Load your dataset into a DataFrame
df = pd.DataFrame({
'score': np.random.normal(70, 12, 2000),
'group': np.random.choice(['A', 'B', 'C'], 2000)
})
# Launch the interactive UI
walker = pyg.walk(df)Sobald die Oberfläche geöffnet ist, ziehen Sie score auf die x-Achse und PyGWalker generiert automatisch ein Histogramm. Sie können die Bin-Größe anpassen, nach group mit Farbkodierung aufteilen, in den Dichtemodus wechseln und das resultierende Diagramm exportieren -- alles ohne zusätzlichen Code zu schreiben. Dies ist besonders nützlich, wenn Sie mehrere Variablen schnell erkunden müssen, bevor Sie den endgültigen matplotlib-Code für einen Bericht schreiben.
Häufig gestellte Fragen
Wie wähle ich die richtige Anzahl von Bins für ein matplotlib-Histogramm?
Beginnen Sie mit bins='auto', das das Maximum der Sturges- und Freedman-Diaconis-Methoden verwendet. Für Daten mit Ausreißern verwenden Sie bins='fd'. Für kleine Datensätze (unter 200 Punkte) funktioniert bins='sturges' gut. Sie können auch eine Ganzzahl übergeben und nach Augenmaß anpassen: Erhöhen Sie die Zahl, wenn die Verteilung zu glatt aussieht, verringern Sie sie, wenn die Balken verrauscht aussehen.
Was ist der Unterschied zwischen density=True und cumulative=True in plt.hist()?
density=True normalisiert das Histogramm, sodass die Gesamtfläche unter allen Balken gleich 1 ist, und konvertiert die y-Achse in Wahrscheinlichkeitsdichte. cumulative=True lässt jeden Balken die Summe aller vorherigen Balken plus sich selbst darstellen. Sie können beides kombinieren: density=True, cumulative=True erzeugt eine kumulative Verteilungsfunktion, bei der der letzte Balken 1,0 erreicht.
Wie überlagere ich zwei Histogramme in matplotlib?
Rufen Sie plt.hist() zweimal mit demselben bins-Wert auf und setzen Sie alpha auf einen Wert kleiner als 1 (z.B. 0,5 oder 0,6), damit beide Verteilungen sichtbar bleiben. Fügen Sie jedem Aufruf label hinzu und schließen Sie mit plt.legend() ab. Die Verwendung von histtype='step' als Alternative vermeidet die Notwendigkeit von Transparenz vollständig, da nur Umrisse gezeichnet werden.
Kann plt.hist() pandas Series und DataFrame-Spalten direkt verarbeiten?
Ja. plt.hist() akzeptiert jede array-ähnliche Eingabe, einschließlich pandas Series. Sie können df['column_name'] direkt übergeben. Zum Plotten aus einem DataFrame mit der eingebauten pandas-Methode verwenden Sie df['column_name'].plot.hist(bins=30), das matplotlib im Hintergrund verwendet.
Wie speichere ich ein matplotlib-Histogramm als Bilddatei?
Nach dem Aufruf von plt.hist() verwenden Sie plt.savefig('histogram.png', dpi=150, bbox_inches='tight') vor plt.show(). Der Parameter bbox_inches='tight' verhindert, dass Beschriftungen abgeschnitten werden. Unterstützte Formate sind PNG, PDF, SVG und EPS.