Es ist immer eine gute Idee, unsere Daten zu untersuchen, bevor wir mit dem Plotten beginnen. Wir können die Daten in einen Pandas-Datenrahmen einlesen und die ersten 10 Zeilen anzeigen:
import pandas as pd# Read in data and examine first 10 rows
flights = pd.read_csv('data/formatted_flights.csv')
flights.head(10)
Die Verspätungen bei der Ankunft von Flügen werden in Minuten angegeben, und negative Werte bedeuten, dass der Flug zu früh war (es stellt sich heraus, dass Flüge oft zu früh ankommen, nur nie dann, wenn wir auf ihnen sind!) Es gibt über 300.000 Flüge mit einer minimalen Verspätung von -60 Minuten und einer maximalen Verspätung von 120 Minuten. Die andere Spalte im Datenrahmen ist der Name der Fluggesellschaft, den wir für Vergleiche verwenden können.
Eine gute Möglichkeit, mit der Untersuchung einer einzelnen Variablen zu beginnen, ist das Histogramm. Ein Histogramm unterteilt die Variable in Bins, zählt die Datenpunkte in jedem Bin und zeigt die Bins auf der x-Achse und die Anzahl auf der y-Achse. In unserem Fall stellen die Bins ein Zeitintervall dar, das die Verspätung der Flüge repräsentiert, und die Zählung ist die Anzahl der Flüge, die in dieses Intervall fallen. Die Bin-Breite ist der wichtigste Parameter für ein Histogramm, und wir sollten immer einige verschiedene Werte für die Bin-Breite ausprobieren, um den besten für unsere Daten auszuwählen.
Um ein einfaches Histogramm in Python zu erstellen, können wir entweder matplotlib oder seaborn verwenden. Der folgende Code zeigt Funktionsaufrufe in beiden Bibliotheken, die gleichwertige Abbildungen erstellen. Bei den Plot-Aufrufen geben wir die Bin-Breite durch die Anzahl der Bins an. Für dieses Diagramm verwende ich Bins mit einer Länge von 5 Minuten, d. h. die Anzahl der Bins entspricht dem Bereich der Daten (von -60 bis 120 Minuten) geteilt durch die Bin-Breite, 5 Minuten ( bins = int(180/5)
).
Für die meisten einfachen Histogramme, Ich würde mich für den matplotlib-Code entscheiden, weil er einfacher ist, aber wir werden die seaborn distplot
-Funktion später verwenden, um verschiedene Verteilungen zu erstellen, und es ist gut, mit den verschiedenen Optionen vertraut zu sein.
Wie bin ich auf 5 Minuten für die binwidth gekommen? Die einzige Möglichkeit, eine optimale binwidth herauszufinden, besteht darin, mehrere Werte auszuprobieren! Im Folgenden finden Sie einen Code, mit dem Sie die gleiche Abbildung in Matplotlib mit einer Reihe von binwidths erstellen können. Letztendlich gibt es keine richtige oder falsche Antwort auf die Bin-Breite, aber ich wähle 5 Minuten, weil ich denke, dass sie die Verteilung am besten repräsentiert.
Die Wahl der Bin-Breite beeinflusst die resultierende Darstellung erheblich. Kleinere Bin-Breiten können das Diagramm unübersichtlich machen, aber größere Bin-Breiten können Nuancen in den Daten verdecken. Matplotlib wählt automatisch eine sinnvolle Bin-Breite für Sie aus, aber ich gebe die Bin-Breite gerne selbst an, nachdem ich mehrere Werte ausprobiert habe. Es gibt keine richtige oder falsche Antwort, also probieren Sie einige Optionen aus und sehen Sie, welche für Ihre speziellen Daten am besten geeignet ist.
Wenn Histogramme versagen
Histogramme sind eine großartige Möglichkeit, um eine einzelne Variable aus einer Kategorie zu untersuchen. Wenn wir jedoch die Verteilungen einer Variablen über mehrere Kategorien hinweg vergleichen wollen, haben Histogramme Probleme mit der Lesbarkeit. Wenn wir beispielsweise die Verteilungen der Ankunftsverspätungen zwischen Fluggesellschaften vergleichen wollen, ist ein Ansatz, der nicht gut funktioniert, die Histogramme für jede Fluggesellschaft auf demselben Diagramm zu erstellen:
(Beachten Sie, dass die y-Achse normalisiert wurde, um die unterschiedliche Anzahl von Flügen zwischen Fluggesellschaften zu berücksichtigen. Geben Sie dazu das Argument norm_hist = True
an den Funktionsaufruf sns.distplot
weiter.)
Dieses Diagramm ist nicht sehr hilfreich! All die sich überschneidenden Balken machen es fast unmöglich, Vergleiche zwischen den Fluggesellschaften anzustellen. Sehen wir uns einige mögliche Lösungen für dieses häufige Problem an.
Lösung Nr. 1: Nebeneinander liegende Histogramme
Anstatt die Histogramme der Fluggesellschaften zu überlappen, können wir sie nebeneinander stellen. Dazu erstellen wir eine Liste der Ankunftsverspätungen für jede Fluggesellschaft und übergeben diese dann als Liste von Listen an den Funktionsaufruf plt.hist
. Wir müssen für jede Fluggesellschaft unterschiedliche Farben und eine Beschriftung angeben, damit wir sie voneinander unterscheiden können. Der Code, einschließlich der Erstellung der Listen für jede Fluggesellschaft, lautet wie folgt:
Wenn wir eine Liste von Listen übergeben, stellt Matplotlib die Balken standardmäßig nebeneinander. Hier habe ich die Bin-Breite auf 15 Minuten geändert, weil das Diagramm sonst zu unübersichtlich ist, aber selbst mit dieser Änderung ist dies keine effektive Abbildung. Es sind zu viele Informationen auf einmal zu verarbeiten, die Balken stimmen nicht mit den Beschriftungen überein, und es ist immer noch schwierig, die Verteilungen zwischen den Fluggesellschaften zu vergleichen. Wenn wir eine Grafik erstellen, soll sie für den Betrachter so einfach wie möglich zu verstehen sein, und diese Abbildung erfüllt dieses Kriterium nicht! Schauen wir uns eine zweite mögliche Lösung an.
Lösung #2: Gestapelte Balken
Anstatt die Balken für jede Fluggesellschaft nebeneinander darzustellen, können wir sie stapeln, indem wir den Parameter stacked = True
an den Histogramm-Aufruf übergeben:
# Stacked histogram with multiple airlines
plt.hist(, bins = int(180/15), stacked=True,
normed=True, color = colors, label=names)
Nun, das ist definitiv nicht besser! Hier wird jede Fluggesellschaft als ein Teil des Ganzen für jeden Bin dargestellt, aber es ist fast unmöglich, Vergleiche anzustellen. Hat zum Beispiel United Air Lines oder JetBlue Airlines bei einer Verspätung von -15 bis 0 Minuten einen größeren Balken? Ich kann es nicht sagen, und die Zuschauer werden es auch nicht können. Ich bin im Allgemeinen kein Befürworter von gestapelten Balken, da sie schwer zu interpretieren sind (obwohl es Anwendungsfälle gibt, z. B. bei der Visualisierung von Proportionen). Beide Lösungen, die wir mit Histogrammen ausprobiert haben, waren nicht erfolgreich, und so ist es an der Zeit, zum Dichte-Diagramm überzugehen.
Dichte-Diagramme
Zunächst, was ist ein Dichte-Diagramm? Ein Dichteplot ist eine geglättete, kontinuierliche Version eines Histogramms, das aus den Daten geschätzt wird. Die gebräuchlichste Form der Schätzung ist die sogenannte Kernel-Dichte-Schätzung. Bei dieser Methode wird für jeden einzelnen Datenpunkt eine kontinuierliche Kurve (der Kernel) gezeichnet, und alle diese Kurven werden dann zu einer einzigen geglätteten Dichteschätzung zusammengefügt. Der am häufigsten verwendete Kernel ist ein Gauß-Kern (der für jeden Datenpunkt eine Gaußsche Glockenkurve erzeugt). Wenn Sie, wie ich, diese Beschreibung etwas verwirrend finden, werfen Sie einen Blick auf die folgende Grafik:
Hier stellt jede kleine schwarze vertikale Linie auf der x-Achse einen Datenpunkt dar. Die einzelnen Kernel (in diesem Beispiel Gauß) sind als gestrichelte rote Linien über jedem Punkt eingezeichnet. Die durchgezogene blaue Kurve entsteht durch die Summierung der einzelnen Gaußschen Kurven und bildet das gesamte Dichte-Diagramm.
Die x-Achse ist der Wert der Variablen, genau wie in einem Histogramm, aber was genau stellt die y-Achse dar? Die y-Achse in einem Dichte-Diagramm ist die Wahrscheinlichkeitsdichtefunktion für die Kernel-Dichte-Schätzung. Wir müssen jedoch darauf achten, dass es sich um eine Wahrscheinlichkeitsdichte und nicht um eine Wahrscheinlichkeit handelt. Der Unterschied besteht darin, dass die Wahrscheinlichkeitsdichte die Wahrscheinlichkeit pro Einheit auf der x-Achse ist. Um sie in eine tatsächliche Wahrscheinlichkeit umzuwandeln, müssen wir die Fläche unter der Kurve für ein bestimmtes Intervall auf der x-Achse ermitteln. Etwas verwirrend ist, dass die y-Achse Werte größer als eins annehmen kann, da es sich um eine Wahrscheinlichkeitsdichte und nicht um eine Wahrscheinlichkeit handelt. Die einzige Voraussetzung für die Darstellung der Dichte ist, dass die Gesamtfläche unter der Kurve zu eins integriert wird. Ich neige im Allgemeinen dazu, die y-Achse in einem Dichte-Diagramm nur als einen Wert für relative Vergleiche zwischen verschiedenen Kategorien zu betrachten.
Dichte-Diagramme in Seaborn
Um Dichte-Diagramme in Seaborn zu erstellen, können wir entweder die Funktion distplot
oder kdeplot
verwenden. Ich werde weiterhin die Funktion distplot
verwenden, weil sie es uns ermöglicht, mehrere Verteilungen mit einem Funktionsaufruf zu erstellen. Wir können zum Beispiel ein Dichte-Diagramm erstellen, das alle Ankunftsverspätungen über dem entsprechenden Histogramm zeigt:
# Density Plot and Histogram of all arrival delays
sns.distplot(flights, hist=True, kde=True,
bins=int(180/5), color = 'darkblue',
hist_kws={'edgecolor':'black'},
kde_kws={'linewidth': 4})
Die Kurve zeigt das Dichte-Diagramm, das im Wesentlichen eine glatte Version des Histogramms ist. Die y-Achse ist als Dichte ausgedrückt, und das Histogramm ist standardmäßig normalisiert, so dass es die gleiche y-Skala wie das Dichteplot hat.
Analog zur Bin-Breite eines Histogramms hat ein Dichteplot einen Parameter, der als Bandbreite bezeichnet wird und die einzelnen Kerne verändert und das Endergebnis des Plots erheblich beeinflusst. Die Plot-Bibliothek wählt für uns einen vernünftigen Wert für die Bandbreite aus (standardmäßig unter Verwendung der ’scott‘-Schätzung), und im Gegensatz zur binwidth eines Histogramms verwende ich normalerweise die Standard-Bandbreite. Wir können jedoch auch andere Bandbreiten verwenden, um zu sehen, ob es eine bessere Wahl gibt. In der Darstellung ist „scott“ die Standardeinstellung, was die beste Option zu sein scheint.
Beachten Sie, dass eine größere Bandbreite zu einer stärkeren Glättung der Verteilung führt. Wir sehen auch, dass die Dichtekurve über diese Grenzen hinausgeht, obwohl wir unsere Daten auf -60 bis 120 Minuten begrenzt haben. Dies ist ein potenzielles Problem mit einem Dichte-Diagramm: Da für jeden Datenpunkt eine Verteilung berechnet wird, können Daten erzeugt werden, die außerhalb der Grenzen der ursprünglichen Daten liegen. Das kann dazu führen, dass wir auf der x-Achse unmögliche Werte erhalten, die in den ursprünglichen Daten nie vorhanden waren! Übrigens können wir auch den Kernel ändern, wodurch sich die an jedem Datenpunkt gezogene Verteilung und damit die Gesamtverteilung ändert. Für die meisten Anwendungen funktionieren jedoch der Standard-Kernel, Gauß, und die Standard-Bandbreitenschätzung sehr gut.
Lösung #3 Dichte-Diagramm
Nachdem wir nun verstanden haben, wie ein Dichte-Diagramm erstellt wird und was es darstellt, wollen wir sehen, wie es unser Problem der Visualisierung der Ankunftsverspätungen mehrerer Fluggesellschaften lösen kann. Um die Verteilungen in einem Diagramm darzustellen, können wir durch die Fluggesellschaften iterieren und jedes Mal distplot
aufrufen, wobei die Kernel-Dichte-Schätzung auf True und das Histogramm auf False gesetzt wird. Der Code zum Zeichnen der Dichtekurve mit mehreren Fluggesellschaften lautet wie folgt:
Endlich haben wir eine effektive Lösung gefunden! Mit dem Dichte-Diagramm können wir leicht Vergleiche zwischen den Fluggesellschaften anstellen, weil das Diagramm weniger unübersichtlich ist. Da wir nun endlich das gewünschte Diagramm haben, kommen wir zu dem Schluss, dass alle diese Fluggesellschaften eine fast identische Verteilung der Ankunftsverspätungen haben! Es gibt jedoch noch weitere Fluggesellschaften im Datensatz, und wir können eine etwas andere darstellen, um einen weiteren optionalen Parameter für Dichtegrafiken zu veranschaulichen, nämlich die Schattierung der Grafik.
Schattierte Dichtegrafiken
Das Ausfüllen der Dichtegrafik kann uns helfen, zwischen sich überschneidenden Verteilungen zu unterscheiden. Obwohl dies nicht immer ein guter Ansatz ist, kann es helfen, den Unterschied zwischen Verteilungen hervorzuheben. Um die Dichteplots zu schattieren, geben wir shade = True
an das kde_kws
-Argument im distplot
-Aufruf weiter.
sns.distplot(subset, hist = False, kde = True,
kde_kws = {'shade': True, 'linewidth': 3},
label = airline)
Ob man den Plot schattiert oder nicht, ist, wie bei anderen Plot-Optionen, eine Frage, die vom Problem abhängt! Bei diesem Diagramm halte ich es für sinnvoll, weil die Schattierung uns hilft, die Diagramme in den Bereichen, in denen sie sich überschneiden, zu unterscheiden. Jetzt haben wir endlich einige nützliche Informationen: Die Flüge von Alaska Airlines sind tendenziell häufiger früher als die von United Airlines. Wenn Sie das nächste Mal die Wahl haben, wissen Sie, welche Fluggesellschaft Sie wählen müssen!
Teppichdiagramme
Wenn Sie jeden Wert in einer Verteilung und nicht nur die geglättete Dichte anzeigen möchten, können Sie ein Teppichdiagramm hinzufügen. Dabei wird jeder einzelne Datenpunkt auf der x-Achse angezeigt, so dass alle tatsächlichen Werte sichtbar werden. Der Vorteil der Verwendung von distplot
von seaborn ist, dass wir den Rug Plot mit einem einzigen Parameteraufruf von rug = True
hinzufügen können (auch mit einigen Formatierungen).
Bei vielen Datenpunkten kann der Rug Plot überfüllt werden, aber bei einigen Datensätzen kann es hilfreich sein, jeden Datenpunkt zu sehen. Anhand des Rug-Plots lässt sich auch erkennen, wie der Dichteplot Daten „erschafft“, wo keine vorhanden sind, da er für jeden Datenpunkt eine Kernel-Verteilung erstellt. Diese Verteilungen können über den Bereich der ursprünglichen Daten hinausgehen und den Eindruck erwecken, dass Alaska Airlines Verspätungen hat, die sowohl kürzer als auch länger sind als tatsächlich aufgezeichnet. Wir müssen uns vor diesem Artefakt der Dichteplots in Acht nehmen und die Betrachter darauf hinweisen!
Schlussfolgerungen
Dieser Beitrag hat Ihnen hoffentlich eine Reihe von Möglichkeiten zur Visualisierung einer einzelnen Variablen aus einer oder mehreren Kategorien aufgezeigt. Es gibt noch mehr univariate (Einzelvariablen-) Diagramme, die wir erstellen können, wie z. B. empirische kumulative Dichte-Diagramme und Quantil-Quantil-Diagramme, aber für den Moment werden wir es bei Histogrammen und Dichte-Diagrammen (und auch Rug-Plots!) belassen. Machen Sie sich keine Sorgen, wenn die Optionen überwältigend erscheinen: Mit etwas Übung wird es einfacher, eine gute Wahl zu treffen, und Sie können bei Bedarf immer um Hilfe bitten. Außerdem gibt es oft keine optimale Wahl, und die „richtige“ Entscheidung hängt von den Vorlieben und den Zielen der Visualisierung ab. Das Gute daran ist, dass es für jede Art von Darstellung, die Sie erstellen möchten, einen Weg gibt, sie in Python zu erstellen! Visualisierungen sind ein effektives Mittel, um Ergebnisse zu kommunizieren, und wenn wir alle verfügbaren Optionen kennen, können wir die richtige Abbildung für unsere Daten wählen.
Ich freue mich über Feedback und konstruktive Kritik und bin auf Twitter unter @koehrsen_will zu erreichen.