W świecie Python’a standardem w wizualizacji danych jest biblioteka matplotlib. Ma ona naprawdę ogromne możliwości, jednak stworzenie niestandardowych wykresów wymaga umiejętności co najmniej na poziomie ninja. Z odsieczą przychodzi nam seaborn – statistical data visualization library.
Biblioteka seaborn swojego czasu była moim odkryciem na miarę bursztynowej komnaty lub „złotego pociągu” spod Wałbrzycha. Tęsknota za lśniącymi wykresami była w moim sercu od dawana. To ona kazała mi przekopywać Stack Overflow oraz dokumentację od matplotlib w poszukiwaniu tych kilku komend, które uczynią wykresy piękniejszymi. Pozwolą w nowy, interesujący i przemawiający do wyobraźni sposób wizualizować dane. Już nie pamiętam, ile to haków stosowałem, aby uzyskać ciekawy efekt.
Aż tu nagle w zaułkach internetów przyczaiła się biblioteka seaborn. Gdy wszedłem na zakładkę z galerią, blask który bił z przykładów poraził moje oczy. Serce zaczęło mocniej bić, ręce zaczęły się pocić i ta jedna myśl świdrowała mi w głowie: „od teraz wszystko się zmieni”. Nie mogłem uwierzyć, w końcu to znalazłem, prostą i piękną bibliotekę do wizualizacji. Już widziałem oczami wyobraźni, zazdrosne spojrzenia kolegów i zalotne uśmiechy koleżanek, na widok pięknie wypolerowanych wykresów z przyciemnianymi szybami i reflektorami ksenonowymi.
Po kilku chwilach testowania dostępnych przykładów, kolejne pozytywne zaskoczenie – współpracuje z Pandas dataframe. Koniec męczarni, nie trzeba będzie już wyciągać serii danych z dataframe’a, by tylko przekształcać je do tablicy, aby następnie zrobić wykres w matplotlib.
Piękne wykresy w python – jakie to proste
Pierwsze spojrzenie młodego adepta Data Science na galerię może zauroczyć. Od razu prężą się i lśnią kolorowe krzywe w przyjaznych dla oka kolorach. Nie są to jakieś normalne krzywe, ma się wrażenie jakby było się w ZOO dziwolągów, których matplotlib nigdy nie będzie w stanie stworzyć. To czym zachwyca seaborn to przede wszystkim świetnie dobrana paleta kolorów, tworzenie powiązanych wykresów oraz możliwość generowania ich na podstawie dataframe’a z biblioteki Pandas.
W galerii mamy liczne przykłady diagramów i wykresów wraz z kodami źródłowymi, w których w kilku liniach możemy stworzyć wykres, który w matplotlib byłby niemożliwy lub ilość kodu do napisania zniechęciła by nawet samego Linusa Torvaldsa.
Niestety w tym wszystkim jest pewien haczyk. Biblioteka ta wymaga od nas … myślenia. Wybranie odpowiedniego typu wykresu nie jest prostą sprawą, wymaga doświadczenia i często znajomości szczegółów implementacyjnych poszczególnych wykresów. Wielokrotnie, gdy na pierwszy rzut oka sądziłem, że dany diagram będzie idealny to po wczytaniu się w dokumentację i próbach jego stworzenia okazywało się, że źle wybrałem.
Poniżej przedstawiam, kilka swoich typów, które stosuję najczęściej.
Scatter plot wraz z prostą regresji
Ten typ wykresu (funkcja lmplot) jest dla mnie zbawieniem, w praktycznie jednej linii kodu jesteśmy w stanie narysować chmurę punktów wraz z wyznaczoną dla nich prostą regresji. Co więcej, gdy dane zasilane są z dataframe’a to możemy wskazać, która kolumna odpowiada za serię (odcień?) danych (argument hue), a która za kolejny wykres (argument col). Zoabaczcie, w jaki prosty sposób można stworzyć serię wykresów przedstawiających informację o napiwkach, kto i kiedy daje najwięcej, jest to nieco zmodyfikowany przykład z dokumentacji:
import seaborn as sns sns.set(color_codes=True) # Load the example tips dataset tips = sns.load_dataset("tips") # Plot tip as a function of total bill across days g = sns.lmplot(x="total_bill", y="tip", hue="day", col="sex", data=tips, size=7) # Use more informative axis labels than are provided by default g.set_axis_labels("Total bill ($)", "Tip ($)")
Tabela z danymi wygląda następująco:
total_bill | tip | sex | smoker | day | time | size | |
---|---|---|---|---|---|---|---|
0 | 16.99 | 1.01 | Female | No | Sun | Dinner | 2 |
1 | 10.34 | 1.66 | Male | No | Sun | Dinner | 3 |
2 | 21.01 | 3.50 | Male | No | Sun | Dinner | 3 |
3 | 23.68 | 3.31 | Male | No | Sun | Dinner | 2 |
4 | 24.59 | 3.61 | Female | No | Sun | Dinner | 4 |
W dataframe mamy informację o wysokości rachunku (total_bill), wysokości napiwku (tip), płeć (sex), czy palacz (smoker), dzień tygodnia (day), pora dnia (time), ile osób (size).
Wykresy pozwalają na przedstawienie liniowej zależności y od x. W naszym przykładzie wielkości napiwku (y=”tip”) od wielkości całego rachunku (x=”total_bill”). Dodatkowo chcemy te zależności przedstawić oddzielnie dla poszczególnych dni tygodnia (hue=”day”) oraz stworzyć dwa wykresy oddzielnie dla mężczyzn i kobiet (sex). W matplotlib trzeba by było zdecydowanie więcej kodu, aby osiągnąć podobny efekt.
Kilka wykresów w jednym oknie dla wielu kombinacji zmiennych
Funkcja pairplot pozwala wygenerować wiele wykresów w jednym oknie (tablicę wykresów). Każdy wewnętrzny wykres przedstawia zależność pomiędzy dwoma wybranymi zmiennymi z wybranego przez nas podzbioru (kolumn z dataframe).
Kluczowe jest zrozumienie dwóch argumentów tej funkcji:
- vars, {x,y}_vars pozwalają one określić podzbiór zmiennych (kolumn z dataframe’a), które zostaną wzięte do zestawienia. Rzadko będziemy chcieli wyznaczyć zależności pomiędzy wszystkimi możliwymi zmiennymi.
- kind – określa jaki typ wykresu będzie poza główną przekątną, czyli tam, gdzie chcemy zobaczyć zależność pomiędzy parametrami. Domyślnie „scatter” czyli kropkowany 🙂
- diag_kind – określa jaki typ wykresu będzie na głównej przekątnej, czyli tam gdzie mamy zależność pomiędzy tą samą zmienną. Domyślnie „hist” czyli histogram (rozkład cechy).
Poniższy kawałek kodu pokazuje jak prosto możemy wygenerować kilka wykresów w jednym oknie przedstawiając zależności pomiędzy trzema parametrami: 'sepal_length’, 'sepal_width’, 'petal_length’. Jak w każdej sytuacji diabeł tkwi w szczegółach, należy mieć już odpowiednio przygotowane dane.
import seaborn as sns sns.set() iris = sns.load_dataset("iris") sns.pairplot(iris, vars=['sepal_length','sepal_width','petal_length'], hue="species", palette="husl")
Przygotowując dane powinniśmy doprowadzić do sytuacji, w której nasze zmienne mamy w kolumnach. W naszym przykładzie z kwiatem iris’a dane mają postać:
sepal_length | sepal_width | petal_length | petal_width | species | |
---|---|---|---|---|---|
0 | 5.1 | 3.5 | 1.4 | 0.2 | setosa |
1 | 4.9 | 3.0 | 1.4 | 0.2 | setosa |
2 | 4.7 | 3.2 | 1.3 | 0.2 | setosa |
3 | 4.6 | 3.1 | 1.5 | 0.2 | setosa |
4 | 5.0 | 3.6 | 1.4 | 0.2 | setosa |
… | … | … | … | … | … |
145 | 6.7 | 3.0 | 5.2 | 2.3 | virginica |
146 | 6.3 | 2.5 | 5.0 | 1.9 | virginica |
147 | 6.5 | 3.0 | 5.2 | 2.0 | virginica |
148 | 6.2 | 3.4 | 5.4 | 2.3 | virginica |
149 | 5.9 | 3.0 | 5.1 | 1.8 | virginica |
Zostanie wygenerowany wykres:
Zwróćcie uwagę na zmienne, które zostały wzięte pod uwagę. Powtórzę się, ale wcześniej stworzenie tego typu wykresu zajmowało dużo czasu, bo trzeba było oprogramować subplot’ing samemu. Tutaj dostajemy to już na tacy.
Axis grids – wykresy w formie grida
Z racji długosci posta nie będę przytaczał kolejnych przykładów, mam nadzieję że powyższe dały wam przedsmak tego co potrafi Seaborn. Na koniec chciabłby skierować waszą uwagę na to co mnie najbardziej ujeło w tej bibliotece, czyli wykesy typu axis grid: FacetGrid, JointGrid, PairGrid (przytoczony powyżej). Pozwalają na szybkie wygenerowanie zestawów wykresów, zainteresowanych odsyłam do dokumentacji.
Podsumowanie
Na początku chcę zaznaczyć, że seaborn nie ma na celu zastąpić matplotlib. Biblioteka ta dodaje kilka typów wykresów, które ciężko jest przygotować z matplotlib. Seaborn szczególnie przydaje się do tworzenia bardziej zaawansowanych wizualizacji, uwzględniających wiele zależnych od siebie danych i typów wykresów (pairplot, kdeplot, joinplot itp). Czasami może to prowadzić do frustracji, gdy prosty wykres chcemy zrobić w seaborn. Ja sam złapałem się na tym, że na siłę chciałem wykorzystać tę bibliotekę, gdzie matplotlib z powodzeniem by sobie poradziła. Moim delikatnym rozczarowaniem jest współpraca z pandas, w szczególności brak wsparcia dla bardziej złożonych struktur. Biblioteka zazwyczaj wymaga płaskiej struktury dataframe’a.
Na wielki plus z mojej strony zasługują domyślne zestawy kolorów, teł i wyglądu linii, dzięki temu nawet nie musiałem się zastanawiać czy coś ulepszyć, bo nie było takiej potrzeby, w matplotlib zawsze sporo czasu spędzałem, aby zrobić 'face lifting’ wykresów.
Materiały dostępne w sieci:
- http://blog.insightdatalabs.com/advanced-functionality-in-seaborn/ – jak zacząć pracę z seaborn oraz co potrafi
- https://www.oreilly.com/learning/data-visualization-with-seaborn – przekrojowy wpis zawierający omówienie podstaw pracy i typó wykresów
- http://www.randalolson.com/2014/06/28/how-to-make-beautiful-data-visualizations-in-python-with-matplotlib/ – niezwiązany z seaborn, pokazujący co można zrobić z samym matplotlib