Direkt zum Inhalt
HeimAnleitungenPython

Histogramme in Matplotlib

Lerne etwas über Histogramme und wie du sie mit Hilfe von matplotlib nutzen kannst, um Erkenntnisse aus Daten zu gewinnen.
Aktualisierte 11. Sept. 2024  · 8 Min. lesen

Einführung

Laut Wikipediaist ein Histogramm eine genaue grafische Darstellung der Verteilung von numerischen Daten. Sie ist eine Schätzung der Wahrscheinlichkeitsverteilung einer kontinuierlichen Variable (quantitative Variable) und wurde erstmals von Karl Pearson eingeführt. Es ist eine Art Balkendiagramm. Um ein Histogramm zu erstellen, musst du zunächst den Wertebereich "binden" - das heißt, den gesamten Wertebereich in eine Reihe von Intervallen unterteilen - und dann zählen, wie viele Werte in jedes Intervall fallen. Die Bins werden in der Regel als aufeinanderfolgende, sich nicht überschneidende Intervalle einer Variablen angegeben. Die Bins (Intervalle) müssen nebeneinander liegen und sind oft (aber nicht zwingend) gleich groß.

Abgesehen von numerischen Daten können Histogramme auch dazu verwendet werden, die Verteilung von Bildern zu visualisieren, denn Bilder sind nichts anderes als eine Kombination von Bildelementen (Pixeln), die von $0$ bis $255$ reichen. Die x-Achse des Histogramms gibt die Anzahl der Bins an, während die y-Achse die Häufigkeit eines bestimmten Bins darstellt. Die Anzahl der Bins ist ein Parameter, der variiert werden kann, je nachdem, wie du die Verteilung deiner Daten visualisieren möchtest.

Zum Beispiel: Angenommen, du möchtest ein Histogramm eines RGB-Bildes mit Pixelwerten zwischen $0$ und $255$ erstellen. Dieses Bild kann maximal 255$ Bins haben. Wenn du die x_Achse (Anzahl der Bins) auf $255$ festlegst, gibt die y_Achse die Häufigkeit der einzelnen Pixel in diesem Bild an.

Histogramme sind ähnlich wie bar Diagramme. Schauen wir uns ein bildhaftes Beispiel für ein Histogramm an:

Ein Histogramm ist ein hervorragendes Instrument zur Visualisierung und zum Verständnis der Wahrscheinlichkeitsverteilung von numerischen Daten oder Bilddaten, das fast jeder intuitiv versteht. Python hat viele verschiedene Möglichkeiten, Histogramme zu erstellen und zu zeichnen. Python hat nur wenige integrierte Bibliotheken für die Erstellung von Graphen. Eine dieser Bibliotheken ist matplotlib.

Im heutigen Lernprogramm wirst du vor allem verwenden matplotlib verwenden, um Histogramme für verschiedene Arten von Datensätzen zu erstellen und zu visualisieren.

Also lasst uns ohne Umschweife loslegen.

Histogramme mit NumPy und Matplotlib aufzeichnen

import numpy as np

Zur Reproduzierbarkeit verwendest du die Funktion seed von numPy, die bei jeder Ausführung die gleiche Ausgabe liefert.

Du zeichnest das Histogramm von gaussian (normal) distribution auf, das einen Mittelwert von $0$ und eine Standardabweichung von $1$ hat.

np.random.seed(100)
np_hist = np.random.normal(loc=0, scale=1, size=1000)
np_hist[:10]
array([-1.74976547,  0.3426804 ,  1.1530358 , -0.25243604,  0.98132079,
        0.51421884,  0.22117967, -1.07004333, -0.18949583,  0.25500144])

Überprüfen wir den Mittelwert und die Standardabweichung der obigen Verteilung.

np_hist.mean(),np_hist.std()
(-0.016772157343909157, 1.0458427194167)

Als Nächstes verwendest du die Funktion histogram von numPy, die hist und bin_edges zurückgibt.

hist,bin_edges = np.histogram(np_hist)
hist
array([  7,  37, 111, 207, 275, 213, 105,  31,  10,   4])
bin_edges
array([-3.20995538, -2.50316588, -1.79637637, -1.08958687, -0.38279736,
        0.32399215,  1.03078165,  1.73757116,  2.44436066,  3.15115017,
        3.85793967])

Als Nächstes stellen wir das Histogramm mit der Funktion plt.bar von matplotlib dar, wobei die x-Achse bin_edges und die y-Achse hist sein werden.

import matplotlib.pyplot as plt
%matplotlib inline
plt.figure(figsize=[10,8])

plt.bar(bin_edges[:-1], hist, width = 0.5, color='#0504aa',alpha=0.7)
plt.xlim(min(bin_edges), max(bin_edges))
plt.grid(axis='y', alpha=0.75)
plt.xlabel('Value',fontsize=15)
plt.ylabel('Frequency',fontsize=15)
plt.xticks(fontsize=15)
plt.yticks(fontsize=15)
plt.ylabel('Frequency',fontsize=15)
plt.title('Normal Distribution Histogram',fontsize=15)
plt.show()

Runden wir die bin_edges auf eine ganze Zahl.

bin_edges = np.round(bin_edges,0)
plt.figure(figsize=[10,8])

plt.bar(bin_edges[:-1], hist, width = 0.5, color='#0504aa',alpha=0.7)
plt.xlim(min(bin_edges), max(bin_edges))
plt.grid(axis='y', alpha=0.75)
plt.xlabel('Value',fontsize=15)
plt.ylabel('Frequency',fontsize=15)
plt.xticks(fontsize=15)
plt.yticks(fontsize=15)
plt.ylabel('Frequency',fontsize=15)
plt.title('Normal Distribution Histogram',fontsize=15)
plt.show()

Jetzt sieht die Grafik viel besser aus, oder?

Um hist und bin_edges zu verstehen, schauen wir uns ein Beispiel an:

Du wirst ein Array mit beliebigen Werten definieren und Bins mit einem Bereich von $5$ festlegen.

hist, bin_edges = np.histogram([1, 1, 2, 2, 2, 2, 3],bins=range(5))
hist
array([0, 2, 4, 1])

In der obigen Ausgabe zeigt hist an, dass sich $0$ in Feld $0$, $2$ in Feld $1$, $4$ in Feld $3$ und $1$ in Feld $4$ befinden.

bin_edges
array([0, 1, 2, 3, 4])

Ähnlich bedeutet die obige Ausgabe von bin_edges, dass Bin $0$ im Intervall $[0,1)$, Bin $1$ im Intervall $[1,2)$, Bin $2$ im Intervall $[2,3)$ und Bin $3$ im Intervall $[3,4)$ liegt.

Ein Histogramm nur mit Matplotlib zeichnen

Die Erstellung eines Histogramms mit matplotlib ist ein Kinderspiel. Alles, was du tun musst, ist die Funktion plt.hist() von matplotlib zu verwenden und die Daten zusammen mit der Anzahl der Bins und einigen optionalen Parametern zu übergeben.

Wenn du in plt.hist() bins='auto' angibst, erhältst du die "ideale" Anzahl von Bins. Es geht darum, eine Bin-Breite zu wählen, die deine Daten möglichst genau wiedergibt.

Das ist alles. Stellen wir also das Histogramm des normal_distribution dar, das du mit numpy erstellt hast.

plt.figure(figsize=[10,8])
n, bins, patches = plt.hist(x=np_hist, bins=8, color='#0504aa',alpha=0.7, rwidth=0.85)
plt.grid(axis='y', alpha=0.75)
plt.xlabel('Value',fontsize=15)
plt.ylabel('Frequency',fontsize=15)
plt.xticks(fontsize=15)
plt.yticks(fontsize=15)
plt.ylabel('Frequency',fontsize=15)
plt.title('Normal Distribution Histogram',fontsize=15)
plt.show()

Zwei Histogramme zusammen aufzeichnen

plt.figure(figsize=[10,8])
x = 0.3*np.random.randn(1000)
y = 0.3*np.random.randn(1000)
n, bins, patches = plt.hist([x, y])

Histogramm von Irisdaten mit Pandas aufzeichnen

Du verwendest sklearn, um einen Datensatz namens iris zu laden. In Sklearn gibt es eine Bibliothek namens Datasets, in der du den Iris-Datensatz findest, der sofort geladen werden kann. Lass uns also schnell den Iris-Datensatz laden.

from sklearn.datasets import load_iris
import pandas as pd
data = load_iris().data
names = ['sepal-length', 'sepal-width', 'petal-length', 'petal-width']

Als Nächstes erstellst du den Datenrahmen des iris Datensatzes.

dataset = pd.DataFrame(data,columns=names)
dataset.head()
  Kelchblatt-Länge Kelchblatt-Breite Blütenblatt-Länge Blütenblatt-Breite
0 5.1 3.5 1.4 0.2
1 4.9 3.0 1.4 0.2
2 4.7 3.2 1.3 0.2
3 4.6 3.1 1.5 0.2
4 5.0 3.6 1.4 0.2
dataset.columns[0]
'sepal-length'

Schließlich verwendest du die integrierte Funktion pandas .hist() , die Histogramme für alle im Datensatz vorhandenen Merkmale erstellt.

Ist das nicht wunderbar?

fig = plt.figure(figsize = (8,8))
ax = fig.gca()
dataset.hist(ax=ax)
plt.show()

Blütenblattlänge, Blütenblattbreite und Kelchblattlänge zeigen eine unimodale Verteilung, während die Kelchblattbreite eine Gaußsche Kurve widerspiegelt. All das sind nützliche Analysen, denn dann kannst du dir überlegen, ob du einen Algorithmus verwendest, der mit dieser Art der Verteilung gut funktioniert.

Histogramm mit Matplotlib aufzeichnen

plt.figure(figsize=[10,10])
f,a = plt.subplots(2,2)
a = a.ravel()
for idx,ax in enumerate(a):
    ax.hist(dataset.iloc[:,idx], bins='auto', color='#0504aa',alpha=0.7, rwidth=0.85)
    ax.set_title(dataset.columns[idx])
plt.tight_layout()
<Figure size 720x720 with 0 Axes>

Histogramm von binären und RGB-Bildern aufzeichnen

Im letzten Abschnitt des Tutorials visualisierst du zwei verschiedene Bilder: Binärbilder (Dokumente) und natürliche Bilder. Binäre Bilder sind Bilder, deren Pixelwerte meist $0$ oder $255$ sind, während ein Farbkanalbild einen Pixelwert zwischen $0$ und $255$ haben kann.

Die Analyse der Pixelverteilung durch Aufzeichnen eines Histogramms der Intensitätswerte eines Bildes ist der richtige Weg, um das Vorkommen jedes Pixels für ein bestimmtes Bild zu messen. Für ein 8-Bit-Graustufenbild gibt es 256 mögliche Intensitätswerte. Um den Unterschied zwischen dem Dokument und dem natürlichen Bild im Bereich der Pixelverteilung zu untersuchen, zeichnest du also jeweils zwei Histogramme für das Dokument und das natürliche Bild. Wenn man bedenkt, dass lesbare Dokumente spärlich sind, sollte die Verteilung der Pixel in diesen Dokumentenbildern meist schief sein.

Du verwendest das Modul opencv, um die beiden Bilder zu laden, sie in Graustufen umzuwandeln, indem du beim Einlesen einen Parameter $0$ übergibst, und sie schließlich auf dieselbe Größe zu bringen.

import cv2
lena_rgb = cv2.imread('lena.png')
lena_gray = cv2.cvtColor(lena_rgb,cv2.COLOR_BGR2GRAY)
lena_gray.shape
(512, 512)
binary = cv2.imread('binary.png')
binary.shape
(1394, 2190, 3)
binary = cv2.resize(binary,(512,512),cv2.INTER_CUBIC)
binary.shape
(512, 512, 3)
binary_gray = cv2.cvtColor(binary,cv2.COLOR_BGR2GRAY)
binary_gray.shape
(512, 512)

Lass uns sowohl das natürliche als auch das Dokumentenbild visualisieren.

plt.figure(figsize=[10,10])

plt.subplot(121)
plt.imshow(lena_rgb[:,:,::-1])
plt.title("Natural Image")

plt.subplot(122)
plt.imshow(binary[:,:,::-1])
plt.title("Document Image")
plt.show()

Hinweis: Du verwendest bins gleich $255$, da es insgesamt $255$ Pixel in einem Bild gibt und du die Häufigkeit jedes Pixelwerts des Bildes zwischen $0$ und $255$ darstellen willst.

hist, edges = np.histogram(binary_gray,bins=range(255))
plt.figure(figsize=[10,8])

plt.bar(edges[:-1], hist, width = 0.8, color='#0504aa')
plt.xlim(min(edges), max(edges))
plt.grid(axis='y', alpha=0.75)
plt.xlabel('Value',fontsize=15)
plt.ylabel('Frequency',fontsize=15)
plt.xticks(fontsize=15)
plt.yticks(fontsize=15)
plt.ylabel('Frequency',fontsize=15)
plt.title('Document Image Histogram',fontsize=15)
plt.show()
hist, edges = np.histogram(lena_gray,bins=range(260))
plt.figure(figsize=[10,8])

plt.bar(edges[:-1], hist, width = 0.5, color='#0504aa')
plt.xlim(min(edges), max(edges))
plt.grid(axis='y', alpha=0.75)
plt.xlabel('Pixels',fontsize=15)
plt.ylabel('Frequency of Pixels',fontsize=15)
plt.xticks(fontsize=15)
plt.yticks(fontsize=15)
plt.ylabel('Frequency',fontsize=15)
plt.title('Natural Image Histogram',fontsize=15)
plt.show()

Aus den obigen Abbildungen kannst du ersehen, dass natural image über alle 256 Intensitäten verteilt ist und eine random Verteilung aufweist, während das Dokumentenbild eine unimodal Verteilung aufweist und hauptsächlich zwischen den Pixelwerten $0$ bis $255$ schief ist.

Fazit

Herzlichen Glückwunsch zum Abschluss des Tutorials.

Dieses Tutorial war ein guter Ausgangspunkt dafür, wie du mit Matplotlib und der Hilfe von Numpy und Pandas ein Histogramm erstellen kannst.

Du hast auch gelernt, wie du die Macht der Histogramme nutzen kannst, um zwischen zwei verschiedenen Bildbereichen zu unterscheiden, nämlich zwischen Dokumenten und natürlichen Bildern.

Wenn du mehr über Datenvisualisierungstechniken erfahren möchtest, solltest du den DataCamp-Kurs "Datenvisualisierung mit Matplotlib " besuchen.

Wenn du Fragen zu diesem Tutorial hast, kannst du sie gerne in den Kommentaren unten stellen.

Themen

Erfahre mehr über Python

Zertifizierung verfügbar

Course

Einführung in die Datenvisualisierung mit Matplotlib

4 hr
172.4K
Lerne, wie du mit Matplotlib Datenvisualisierungen erstellst, anpasst und teilst.
See DetailsRight Arrow
Start Course
Mehr anzeigenRight Arrow