Zawsze dobrze jest sprawdzić nasze dane, zanim zaczniemy je wykreślać. Możemy wczytać dane do ramki danych pandas i wyświetlić pierwsze 10 wierszy:

import pandas as pd# Read in data and examine first 10 rows
flights = pd.read_csv('data/formatted_flights.csv')
flights.head(10)
Head of Dataframe

Opóźnienia przylotów podawane są w minutach, a ujemne wartości oznaczają, że lot był wcześniejszy (okazuje się, że loty często mają tendencję do wcześniejszego przylotu, tylko nigdy wtedy, gdy my na nich jesteśmy)! Istnieje ponad 300 000 lotów z minimalnym opóźnieniem wynoszącym -60 minut i maksymalnym 120 minut. Inną kolumną w ramce danych jest nazwa linii lotniczej, której możemy użyć do porównań.

Świetnym sposobem na rozpoczęcie badania pojedynczej zmiennej jest histogram. Histogram dzieli zmienną na biny, zlicza punkty danych w każdym binie i pokazuje biny na osi x, a zliczenia na osi y. W naszym przypadku, biny będą przedziałami czasu reprezentującymi opóźnienie lotów, a zliczanie będzie liczbą lotów mieszczących się w tym przedziale. Szerokość bloku jest najważniejszym parametrem histogramu i zawsze powinniśmy wypróbować kilka różnych wartości szerokości bloku, aby wybrać najlepszą dla naszych danych.

Aby utworzyć podstawowy histogram w Pythonie, możemy użyć matplotlib lub seaborn. Poniższy kod pokazuje wywołania funkcji w obu bibliotekach, które tworzą równoważne figury. Dla wywołań funkcji plot, określamy szerokość binu przez liczbę binów. Dla tego wykresu użyję bloków o długości 5 minut, co oznacza, że liczba bloków będzie równa zakresowi danych (od -60 do 120 minut) podzielonemu przez szerokość bloku, 5 minut ( bins = int(180/5)).

Histogram (odpowiednik rysowany zarówno przez matplotlib, jak i seaborn)

Dla najbardziej podstawowych histogramów, Poszedłbym z kodem matplotlib, ponieważ jest prostszy, ale będziemy używać funkcji seaborn distplot później do tworzenia różnych rozkładów i dobrze jest być zaznajomionym z różnymi opcjami.

Jak wymyśliłem 5 minut dla szerokości bloku? Jedynym sposobem na znalezienie optymalnej szerokości bloku jest wypróbowanie wielu wartości! Poniżej znajduje się kod do wykonania tej samej figury w matplotlib z różnymi szerokościami binarnymi. Ostatecznie, nie ma dobrej lub złej odpowiedzi na pytanie o szerokość bloku, ale wybrałem 5 minut, ponieważ uważam, że najlepiej reprezentuje rozkład.

Histogramy z różnymi szerokościami bloku

Wybór szerokości bloku znacząco wpływa na wynikową fabułę. Mniejsze szerokości binu mogą sprawić, że wykres będzie zagracony, ale większe szerokości binu mogą przesłonić niuanse w danych. Matplotlib automatycznie wybierze dla ciebie rozsądną szerokość binów, ale ja lubię samemu określić szerokość binów po wypróbowaniu kilku wartości. Nie ma prawdziwej dobrej lub złej odpowiedzi, więc wypróbuj kilka opcji i zobacz, która działa najlepiej dla twoich konkretnych danych.

Gdy histogramy zawodzą

Histogramy są świetnym sposobem na rozpoczęcie badania pojedynczej zmiennej pochodzącej z jednej kategorii. Jednakże, gdy chcemy porównać rozkłady jednej zmiennej w wielu kategoriach, histogramy mają problemy z czytelnością. Na przykład, jeśli chcemy porównać rozkłady opóźnień przylotów pomiędzy liniami lotniczymi, podejściem, które nie działa dobrze, jest utworzenie histogramów dla każdej linii lotniczej na tym samym wykresie:

Overlapping Histograms with Multiple Airlines

(Zauważ, że oś y została znormalizowana, aby uwzględnić różną liczbę lotów pomiędzy liniami lotniczymi. Aby to zrobić, należy przekazać argument norm_hist = True do wywołania funkcji sns.distplot.)

Ten wykres nie jest zbyt pomocny! Wszystkie nakładające się na siebie słupki prawie uniemożliwiają dokonywanie porównań między liniami lotniczymi. Przyjrzyjmy się kilku możliwym rozwiązaniom tego powszechnego problemu.

Rozwiązanie #1: Histogramy obok siebie

Zamiast nakładać na siebie histogramy linii lotniczych, możemy umieścić je obok siebie. Aby to zrobić, tworzymy listę opóźnień przylotów dla każdej linii lotniczej, a następnie przekazujemy ją do wywołania funkcji plt.hist jako listę list. Musimy określić różne kolory dla każdej linii lotniczej oraz etykietę, abyśmy mogli je od siebie odróżnić. Kod, w tym tworzenie list dla każdej linii lotniczej, znajduje się poniżej:

Domyślnie, jeśli przekażemy listę list, matplotlib umieści słupki obok siebie. Tutaj zmieniłem binwidth na 15 minut, ponieważ w przeciwnym razie wykres jest zbyt zagracony, ale nawet z tą modyfikacją nie jest to efektywna figura. Jest zbyt wiele informacji do przetworzenia na raz, słupki nie są wyrównane do etykiet i nadal trudno jest porównać rozkłady pomiędzy liniami lotniczymi. Kiedy tworzymy wykres, chcemy, aby był on jak najłatwiejszy do zrozumienia dla widza, a ten rysunek nie spełnia tych kryteriów! Przyjrzyjmy się drugiemu potencjalnemu rozwiązaniu.

Rozwiązanie #2: Słupki ułożone w stos

Zamiast wykreślać słupki dla każdej linii lotniczej obok siebie, możemy ułożyć je w stos, przekazując parametr stacked = True do wywołania histogramu:

# Stacked histogram with multiple airlines
plt.hist(, bins = int(180/15), stacked=True,
normed=True, color = colors, label=names)

Cóż, to zdecydowanie nie jest lepsze! Tutaj każda linia lotnicza jest reprezentowana jako wycinek całości dla każdego binu, ale prawie niemożliwe jest dokonywanie porównań. Na przykład, przy opóźnieniu od -15 do 0 minut, czy United Air Lines lub JetBlue Airlines mają większy rozmiar paska? Ja nie jestem w stanie tego stwierdzić i widzowie też nie będą w stanie. Generalnie nie jestem zwolennikiem ułożonych słupków, ponieważ mogą być trudne do zinterpretowania (chociaż są przypadki użycia, takie jak wizualizacja proporcji). Oba rozwiązania, których próbowaliśmy używając histogramów nie były udane, więc czas przejść do wykresu gęstości.

Plany gęstości

Po pierwsze, co to jest wykres gęstości? Wykres gęstości jest wygładzoną, ciągłą wersją histogramu oszacowanego na podstawie danych. Najbardziej powszechna forma estymacji jest znana jako estymacja gęstości jądra. W tej metodzie, ciągła krzywa (jądro) jest rysowana w każdym indywidualnym punkcie danych, a wszystkie te krzywe są następnie dodawane razem, aby uzyskać pojedynczą gładką estymację gęstości. Najczęściej używanym jądrem jest gaussowski (który tworzy gaussowską krzywą dzwonową w każdym punkcie danych). Jeśli, podobnie jak ja, uważasz, że ten opis jest nieco mylący, spójrz na poniższy wykres:

Kernel Density Estimation (Source)

Tutaj każda mała czarna pionowa linia na osi x reprezentuje punkt danych. Poszczególne jądra (Gaussian w tym przykładzie) są narysowane w przerywanych czerwonych liniach powyżej każdego punktu. Stała niebieska krzywa jest tworzona przez sumowanie poszczególnych Gaussianów i tworzy ogólny wykres gęstości.

Oś x jest wartością zmiennej tak jak w histogramie, ale co dokładnie reprezentuje oś y? Oś y w wykresie gęstości jest funkcją gęstości prawdopodobieństwa dla estymacji gęstości jądra. Musimy jednak uważać, aby określić, że jest to gęstość prawdopodobieństwa, a nie prawdopodobieństwo. Różnica polega na tym, że gęstość prawdopodobieństwa jest prawdopodobieństwem na jednostkę na osi x. Aby przekonwertować na rzeczywiste prawdopodobieństwo, musimy znaleźć obszar pod krzywą dla określonego przedziału na osi x. Nieco mylące jest to, że ponieważ jest to gęstość prawdopodobieństwa, a nie prawdopodobieństwo, oś y może przyjmować wartości większe niż jeden. Jedynym wymogiem wykresu gęstości jest to, że całkowity obszar pod krzywą całkuje się do jednego. Ogólnie mam tendencję do myślenia o osi y na wykresie gęstości jako o wartości tylko do względnych porównań między różnymi kategoriami.

Wykresy gęstości w Seaborn

Aby wykonać wykresy gęstości w Seaborn, możemy użyć funkcji distplot lub kdeplot. Będę nadal używał funkcji distplot, ponieważ pozwala ona na tworzenie wielu rozkładów za pomocą jednego wywołania funkcji. Na przykład, możemy utworzyć wykres gęstości pokazujący wszystkie opóźnienia przylotów na szczycie odpowiedniego histogramu:

# 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})

Plan gęstości i histogram przy użyciu seaborn

Krzywa pokazuje wykres gęstości, który jest zasadniczo wygładzoną wersją histogramu. Oś y jest wyrażona w kategoriach gęstości, a histogram jest domyślnie normalizowany tak, że ma taką samą skalę y jak wykres gęstości.

Analogicznie do szerokości bloku histogramu, wykres gęstości ma parametr zwany szerokością pasma, który zmienia poszczególne jądra i znacząco wpływa na końcowy wynik wykresu. Biblioteka plotująca wybierze dla nas rozsądną wartość szerokości pasma (domyślnie używając estymaty 'scott’), i w przeciwieństwie do szerokości bloku histogramu, ja zazwyczaj używam domyślnej szerokości pasma. Możemy jednak rozważyć użycie różnych szerokości pasma, aby sprawdzić, czy istnieje lepszy wybór. Na wykresie domyślną szerokością pasma jest 'scott’, co wygląda na najlepszą opcję.

Density Plot Showing different Bandwidths

Zauważmy, że szersze pasmo powoduje większe wygładzenie rozkładu. Widzimy również, że mimo iż ograniczyliśmy nasze dane do -60 do 120 minut, wykres gęstości wykracza poza te granice. Jest to jeden z potencjalnych problemów z wykresem gęstości: ponieważ oblicza on rozkład w każdym punkcie danych, może generować dane, które wykraczają poza granice oryginalnych danych. Może to oznaczać, że na osi x pojawią się niemożliwe wartości, które nigdy nie występowały w oryginalnych danych! Możemy również zmienić jądro, które zmienia rozkład wylosowany w każdym punkcie danych, a tym samym ogólny rozkład. Jednakże, dla większości zastosowań, domyślne jądro, Gaussian, i domyślna estymacja szerokości pasma działają bardzo dobrze.

Rozwiązanie #3 Wykres gęstości

Teraz, gdy rozumiemy jak wykres gęstości jest tworzony i co reprezentuje, zobaczmy jak może on rozwiązać nasz problem wizualizacji opóźnień przylotów wielu linii lotniczych. Aby pokazać rozkłady na tym samym wykresie, możemy iterować po liniach lotniczych, za każdym razem wywołując distplot z estymatą gęstości jądra ustawioną na True i histogramem ustawionym na False. Kod do narysowania wykresu gęstości z wieloma liniami lotniczymi znajduje się poniżej:

Wykres gęstości z wieloma liniami lotniczymi

Wreszcie, doszliśmy do skutecznego rozwiązania! Dzięki wykresowi gęstości możemy łatwo dokonywać porównań między liniami lotniczymi, ponieważ wykres jest mniej zagracony. Teraz, gdy w końcu mamy pożądany wykres, dochodzimy do wniosku, że wszystkie te linie lotnicze mają prawie identyczne rozkłady opóźnień przylotów! W zbiorze danych znajdują się jednak inne linie lotnicze i możemy wykreślić jedną, która jest nieco inna, aby zilustrować inny opcjonalny parametr wykresów gęstości – cieniowanie wykresu.

Wypełnianie wykresu gęstości cieniowaniem

Wypełnianie wykresu gęstości może pomóc nam rozróżnić nakładające się rozkłady. Chociaż nie zawsze jest to dobre podejście, może pomóc w podkreśleniu różnic między rozkładami. Aby zacieniować wykresy gęstości, przekazujemy shade = True do argumentu kde_kws w wywołaniu distplot.

sns.distplot(subset, hist = False, kde = True,
kde_kws = {'shade': True, 'linewidth': 3},
label = airline)

Shaded Density Plot

To, czy cieniować wykres, czy nie, jest, podobnie jak inne opcje wykresów, pytaniem zależnym od problemu! W przypadku tego wykresu myślę, że ma to sens, ponieważ cieniowanie pomaga nam rozróżnić wykresy w regionach, w których się pokrywają. Teraz wreszcie mamy kilka przydatnych informacji: Loty Alaska Airlines mają tendencję do bycia wcześniejszymi częściej niż United Airlines. Następnym razem, gdy będziesz miał taką możliwość, będziesz wiedział, którą linię lotniczą wybrać!

Plany dywanowe

Jeśli chcesz pokazać każdą wartość w rozkładzie, a nie tylko wygładzoną gęstość, możesz dodać wykres dywanowy. To pokazuje każdy pojedynczy punkt danych na osi x, pozwalając nam na wizualizację wszystkich rzeczywistych wartości. Zaletą użycia distplot seaborna jest to, że możemy dodać wykres dywanowy za pomocą jednego parametru rug = True (z pewnym formatowaniem).

Density Plot with Rug Plot for Alaska Airlines

Przy wielu punktach danych wykres dywanowy może stać się przepełniony, ale w przypadku niektórych zestawów danych pomocne może być wyświetlenie każdego punktu danych. Wykres dywanowy pozwala nam również zobaczyć, jak wykres gęstości „tworzy” dane tam, gdzie ich nie ma, ponieważ tworzy rozkład jądra w każdym punkcie danych. Rozkłady te mogą wyciekać poza zakres oryginalnych danych i sprawiać wrażenie, że Alaska Airlines ma opóźnienia zarówno krótsze, jak i dłuższe niż faktycznie zarejestrowane. Musimy uważać na ten artefakt wykresów gęstości i wskazywać go widzom!

Wnioski

Ten post, mam nadzieję, dał ci szereg opcji do wizualizacji pojedynczej zmiennej z jednej lub wielu kategorii. Istnieje jeszcze więcej jednoczynnikowych (pojedynczych zmiennych) wykresów, które możemy wykonać, takich jak empiryczne wykresy gęstości skumulowanej i kwantylowe wykresy kwantylowe, ale na razie zostawimy to na histogramach i wykresach gęstości (i wykresach dywanowych też!). Nie przejmuj się, jeśli opcje wydają się przytłaczające: z praktyką dokonanie dobrego wyboru stanie się łatwiejsze, a w razie potrzeby zawsze możesz poprosić o pomoc. Co więcej, często nie ma optymalnego wyboru, a „właściwa” decyzja zależy od preferencji i celów wizualizacji. Dobre jest to, że bez względu na to, jaką działkę chcesz stworzyć, znajdzie się sposób, aby zrobić to w Pythonie! Wizualizacje są skutecznym środkiem do przekazywania wyników, a znajomość wszystkich dostępnych opcji pozwala nam wybrać odpowiednią figurę dla naszych danych.

Witam opinie i konstruktywną krytykę i można mnie znaleźć na Twitterze @koehrsen_will.

admin

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.

lg