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)
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)
).
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.
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:
(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:
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})
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.