Rozdziały 5-6-7¶
- W kolejnych rozdziałach zagłębimy się w wizualizację danych.
- Jak tworzyć wizualizacje w Pythonie?
- O jakich zasadach powinniśmy pamiętać?
- Jak współpracować z Matplotlib, Pyplot?
- Jak pracować nad wizualizacjami w Seaborn?
- Jakie są dobre praktyki tworzenia wizualizacji danych?
- Następnie, zanim przystąpi do analizy statystycznej, będziemy pracować nad zarządzaniem i czyszczeniem naszych danych.
- Jak radzić sobie z brakującymi wartościami?
- Jak sobie poradzić z brudnymi danymi?
- Jakie są podstawowe sposoby opisywania danych?
Pamiętajcie, ze te rozdziały to integralna część Eksploracyjnej Analizy Danych w Pythonie.
W tym rozdziale¶
- Czym jest wizualizacja danych i dlaczego jest ważna?
- Wprowadzenie do
matplotlib
. - Typy wykresów jednowymiarowych:
- Histogramy (jednowymiarowe).
- Wykresy rozrzutu (tzw. scatterplots - dwuwymiarowe).
- Wykresy słupkowe (takze dwuwymiarowe).
Wprowadzenie: wizualizacja danych¶
Czym jest wizualizacja danych?¶
Wizualizacja danych odnosi się do procesu (i wyniku) graficznego przedstawiania danych.
Dla naszych celów w tym rozdziale będziemy mówić głównie o typowych metodach wykresów danych, w tym:
- Histogramy
- Wykresy punktowe
- Wykresy liniowe
- Wykresy słupkowe
Dlaczego wizualizacja danych jest ważna?¶
- Eksploracyjna analiza danych
- Przekazywanie spostrzeżeń
- Pokazywanie ukrytych asocjacji w danych
Wpływ na zrozumienie świata¶
Florence Nightingale (1820-1910) był reformatorem społecznym, statystykiem i założycielem nowoczesnego pielęgniarstwa.

Wpływ na zrozumienie świata (cz. 2)¶
John Snow (1813-1858) był lekarzem, którego wizualizacja ognisk cholery pomogła zidentyfikować źródło i mechanizm rozprzestrzeniania się (zaopatrzenie w wodę).

Wprowadzenie do matplotlib
¶
Ładowanie pakietów¶
Tutaj ładujemy podstawowe pakiety, których będziemy używać.
Dodajemy również kilka linijek kodu, które zapewniają, że nasze wizualizacje będą wykreślane „inline” z naszym kodem i że będą miały ładną, wyraźną jakość.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import scipy.stats as ss
%matplotlib inline
%config InlineBackend.figure_format = 'retina'
Czym jest matplotlib
?¶
matplotlib
to pakiet graficzny dla Pythona.
- Wiele tutoriali dostępnych online.
- Również wiele przykładów
matplotlib
w użyciu.
Zauważ, że seaborn
, (który omówimy wkrótce) używa matplotlib
„pod maską”.
Czym jest pyplot
?¶
pyplot
to zbiór funkcji w ramachmatplotlib
, które naprawdę ułatwiają wykreślanie danych.
Z pyplot
, możemy łatwo wykreślić takie rzeczy jak:
- Histogramy (
plt.hist
) - Wykresy rozrzutu (
plt.scatter
) - Wykresy liniowe (
plt.plot
) - Wykresy słupkowe (
plt.bar
)
Przykładowe dane¶
Załadujmy nasz znajomy zestaw danych Pokemon, który można znaleźć w sekcji data/pokemon.csv
.
df_pokemon = pd.read_csv("data/pokemon.csv")
df_pokemon.head(3)
Histogramy¶
Czym są histogramy?¶
Histogram to wizualizacja pojedynczej ciągłej zmiennej ilościowej (np. dochodu lub temperatury).
- Histogramy są przydatne do sprawdzania, jak rozkłada się zmienna.
- Mogą być używane do określenia, czy rozkład jest normalny, skośny lub bimodalny.
Histogram jest wykresem jednowymiarowym, tj. wyświetla tylko jedną zmienną.
Histogramy w matplotlib
¶
Aby utworzyć histogram, wywołaj plt.hist
z pojedynczą kolumną DataFrame
(lub numpy.ndarray
).
Pytanie: Co mówi nam ten wykres?
p = plt.hist(df_pokemon['Attack'])

Zmiana liczby przedziałów¶
Histogram umieszcza dane ciągłe w przedziałach (np. 1-10, 11-20 itd.).
- Wysokość każdego przedziału odzwierciedla liczbę obserwacji w tym przedziale.
- Zwiększanie lub zmniejszanie liczby przedziałów zapewnia większą lub mniejszą szczegółowość rozkładu.
### Ten wykres ma wiele przedziałów - 30.
p = plt.hist(df_pokemon['Attack'], bins = 30)

### Ten ma mniej
p = plt.hist(df_pokemon['Attack'], bins = 5)

Zmiana poziomu alpha
¶
Poziom alfa
zmienia przezroczystość twojego wykresu.
### ten ma mniej przedziałów
p = plt.hist(df_pokemon['Attack'], alpha = .6)

Sprawdź się¶
Jak stworzyć histogram wyników dla Defense
?
### Twój kod tutaj
Sprawdź się¶
Czy wiesz jak stworzyć histogram wyników dla Typu 1
?
### Twój kod tutaj
Informacja z histogramów¶
Histogramy są niezwykle przydatne do poznawania kształtu naszego rozkładu.
Możemy zadawać pytania takie jak:
- Czy ten rozkład jest względnie normalny?
- Czy rozkład jest skośny?
- Czy są wartości odstające?
Dane o rozkładzie normalnym¶
Możemy użyć funkcji numpy.random.normal
, aby utworzyć rozkład normalny, a następnie go wykreślić.
Rozkład normalny ma następujące cechy:
- Klasyczny kształt “dzwonu” (symetryczny).
- Średnia, mediana i moda są identyczne.
norm = np.random.normal(loc = 10, scale = 1, size = 1000)
p = plt.hist(norm, alpha = .6)

Skośne dane¶
Skośność oznacza, że istnieją wartości wydłużające jeden z „ogonów” rozkładu.
- Skośność dodatnia/prawa: ogon jest skierowany w prawo.
- Ujemny/lewy skośny: ogon jest skierowany w lewo.
rskew = ss.skewnorm.rvs(20, size = 1000) # tworzymy dane prawo-skośne
lskew = ss.skewnorm.rvs(-20, size = 1000) # tworzymy dane lewo-skośne
fig, axes = plt.subplots(1, 2)
axes[0].hist(rskew)
axes[0].set_title("Prawoskośne");
axes[1].hist(lskew)
axes[1].set_title("Lewoskośne");

Punkty odstające¶
Punkty odstające to punkty danych, które znacznie różnią się od innych punktów w rozkładzie.
- W przeciwieństwie do danych skośnych, wartości odstające są zazwyczaj nieciągłe w stosunku do reszty rozkładu.
- W kolejnym rozdziale omówimy więcej sposobów identyfikacji wartości odstających; na razie możemy polegać na histogramach.
norm = np.random.normal(loc = 10, scale = 1, size = 1000)
upper_outliers = np.array([21, 21, 21, 21]) ## trochę odstających
data = np.concatenate((norm, upper_outliers))
p = plt.hist(data, alpha = .6)
plt.arrow(20, 100, dx = 0, dy = -50, width = .3, head_length = 10, facecolor = "red");

p = plt.hist(df_pokemon['HP'], alpha = .6)

p = plt.hist(df_pokemon['Sp. Atk'], alpha = .6)

Sprawdź się¶
W nieco prawoskośnym rozkładzie (jak poniżej), co jest większe - średnia
czy mediana
?
p = plt.hist(df_pokemon['Sp. Atk'], alpha = .6)

Rozwiązanie¶
Średnia
jest najbardziej dotknięta skośnością, więc jest ciągnięta najdalej w prawo w rozkładzie prawoskośnym.
p = plt.hist(df_pokemon['Sp. Atk'], alpha = .6)
plt.axvline(df_pokemon['Sp. Atk'].mean(), linestyle = "dashed", color = "green");
plt.axvline(df_pokemon['Sp. Atk'].median(), linestyle = "dotted", color = "red");

Modyfikacja naszego wykresu¶
- Dobra wizualizacja danych powinna również wyjaśniać, co jest wykreślane.
- Wyraźnie oznaczone osie
x
iy
, tytuł.
- Wyraźnie oznaczone osie
- Czasami możemy również chcieć dodać nakładki.
- Np. przerywaną pionową linię reprezentującą „średnią”.
Etykiety osi¶
p = plt.hist(df_pokemon['Attack'], alpha = .6)
plt.xlabel("Atak")
plt.ylabel("Liczebność")
plt.title("Rozkład punktów za atak");

Linie pionowe¶
plt.axvline
pozwala nam narysować pionową linię w określonej pozycji, np. średnią
kolumny Attack
.
p = plt.hist(df_pokemon['Attack'], alpha = .6)
plt.xlabel("Atak")
plt.ylabel("Liczebność")
plt.title("Rozkład liczby ataków")
plt.axvline(df_pokemon['Attack'].mean(), linestyle = "dotted");

Histogramy z pyplot express
¶
Z pyplot express
równiez mozemy tworzyć histogramy:
import plotly.express as px
df = px.data.tips()
fig = px.histogram(df, x="total_bill")
fig.show()
Z pyplot express
mozemy narysować kilka histogramów dla różnych wartości jednej kolumny:
import plotly.express as px
df = px.data.tips()
fig = px.histogram(df, x="total_bill", color="sex")
fig.show()
Grupowanie histogramów¶
Najciekawsze jest jednak kopanie w danych głębiej - tzw. faceting - grupowanie wykresów:
import plotly.express as px
df = px.data.tips()
fig = px.histogram(df, x="total_bill", y="tip", color="sex", facet_row="time", facet_col="day",
category_orders={"day": ["Thur", "Fri", "Sat", "Sun"], "time": ["Lunch", "Dinner"]})
fig.show()
Wykresy rozrzutu¶
Czym są wykresy rozrzutu?¶
Wykres rozrzutu to wizualizacja tego, jak dwa różne rozkłady ciągłe odnoszą się do siebie.
- Każdy pojedynczy punkt reprezentuje obserwację.
- Bardzo przydatne do eksploracyjnej analizy danych.
- Czy te zmienne są dodatnio czy ujemnie skorelowane?
Wykres rozrzutu jest wykresem dwuwymiarowym, tj. wyświetla co najmniej dwie zmienne.
Wykresy rozrzutu z matplotlib
¶
Możemy utworzyć scatterplot używając plt.scatter(x, y)
, gdzie x
i y
to dwie zmienne, które chcemy wizualizować.
x = np.arange(1, 10)
y = np.arange(11, 20)
p = plt.scatter(x, y)

Sprawdź się¶
Czy te zmienne są ze sobą powiązane? Jeśli tak, to w jaki sposób?
x = np.random.normal(loc = 10, scale = 1, size = 100)
y = x * 2 + np.random.normal(loc = 0, scale = 2, size = 100)
plt.scatter(x, y, alpha = .6);

Sprawdź się¶
Czy te zmienne są ze sobą powiązane? Jeśli tak, to w jaki sposób?
x = np.random.normal(loc = 10, scale = 1, size = 100)
y = -x * 2 + np.random.normal(loc = 0, scale = 2, size = 100)
plt.scatter(x, y, alpha = .6);

Wykrywanie zależności nieliniowych¶
x = np.random.normal(loc = 10, scale = 1, size = 100)
y = np.sin(x)
plt.scatter(x, y, alpha = .6);

Sprawdź się¶
Jak moglibyśmy zwizualizować związek między Attack
i Speed
w naszym zbiorze danych Pokemonów?
### Twój kod tutaj
Wykresy rozrzutu z pyplot express
¶
Wykresy bąbelkowe¶
Wykresy punktowe z okrągłymi znacznikami o zmiennym rozmiarze są często nazywane wykresami bąbelkowymi. Należy pamiętać, że dane dotyczące koloru i rozmiaru są dodawane do informacji o najechaniu kursorem. Można dodać inne kolumny do danych najechania kursorem za pomocą argumentu hover_data
w px.scatter
.
import plotly.express as px
df = px.data.iris()
fig = px.scatter(df, x="sepal_width", y="sepal_length", color="species",
size='petal_length', hover_data=['petal_width'])
fig.show()
Kolor może być ciągły, jak poniżej, lub dyskretny/kategorialny, jak powyżej.
df = px.data.iris()
fig = px.scatter(df, x="sepal_width", y="sepal_length", color='petal_length')
fig.show()
Argument symbolu może być również mapowany na kolumnę. Dostępna jest szeroka gama symboli.
df = px.data.iris()
fig = px.scatter(df, x="sepal_width", y="sepal_length", color="species", symbol="species")
fig.show()
Grupowane wykresy rozrzutu¶
Wykresy rozrzutu wspierają grupowanie - tzw. faceting.
df = px.data.tips()
fig = px.scatter(df, x="total_bill", y="tip", color="smoker", facet_col="sex", facet_row="time")
fig.show()
Dodawanie linii¶
Na wykres rozrzutu nałozyć mozna oszacowaną funkcję liniową:
df = px.data.tips()
fig = px.scatter(df, x="total_bill", y="tip", trendline="ols")
fig.show()
Wykresy słupkowe¶
Czym jest barplot?¶
Wykres słupkowy wizualizuje związek pomiędzy jedną zmienną ciągłą a zmienną kategorialną.
- Wysokość każdego słupka zazwyczaj wskazuje średnią zmiennej ciągłej.
- Każdy słupek reprezentuje inny poziom zmiennej kategorialnej.
Wykres słupkowy jest wykresem dwuwymiarowym, tj. wyświetla co najmniej dwie zmienne.
Wykresy słupkowe z matplotlib
¶
plt.bar
może być użyty do stworzenia wykresu słupkowego naszych danych.
- Na przykład, średni
Attack
wedługLegendarnego
statusu. - Jednak najpierw musimy użyć
groupby
, aby obliczyć średniąAttack
na poziom.
Krok 1: Wykorzystanie groupby
¶
summary = df_pokemon[['Legendary', 'Attack']].groupby("Legendary").mean().reset_index()
summary
### Zmiana "Legendary" na str
summary['Legendary'] = summary['Legendary'].apply(lambda x: str(x))
summary
Krok 2: Przekazanie wartości na plt.bar
¶
Sprawdź się:
- Czego dowiadujemy się z tego wykresu?
- Czego brakuje w tej opowieści?
plt.bar(x = summary['Legendary'],
height = summary['Attack'],
alpha = .6)
plt.xlabel("Status")
plt.ylabel("Atak")

Plotly express¶
Plotly Express to łatwy w użyciu, wysokopoziomowy interfejs do Plotly, który działa na różnych typach danych i tworzy łatwe do stylizacji wykresy.
Dzięki px.bar każdy wiersz ramki DataFrame jest reprezentowany jako prostokątny znak. Aby zagregować wiele punktów danych w ten sam prostokątny znak, należy zapoznać się z dokumentacją histogramu.
W poniższym przykładzie jest tylko jeden wiersz danych na rok, więc wyświetlany jest jeden słupek na rok.
import plotly.express as px
data_canada = px.data.gapminder().query("country == 'Canada'")
fig = px.bar(data_canada, x='year', y='pop')
fig.show()
Wykresy słupkowe z danymi w formacie long
¶
Dane w długim formacie mają jeden wiersz na obserwację i jedną kolumnę na zmienną. Jest to odpowiednie do przechowywania i wyświetlania danych wielowymiarowych, tj. o wymiarze większym niż 2. Format ten jest czasami nazywany „uporządkowanym”.
Aby dowiedzieć się więcej o tym, jak dostarczyć konkretną formę danych zorientowanych na kolumny do funkcji 2D-Cartesian Plotly Express, takich jak px.bar, zobacz dokumentację Plotly Express Wide-Form Support in Python.
long_df = px.data.medals_long()
fig = px.bar(long_df, x="nation", y="count", color="medal", title="Dane w formacie long")
fig.show()
Podejrzyjmy dane:
long_df
Wykresy słupkowe z danymi w formacie wide
¶
Dane w szerokim formacie mają jeden wiersz na wartość jednej z pierwszych zmiennych i jedną kolumnę na wartość drugiej zmiennej.
Jest to odpowiednie do przechowywania i wyświetlania danych dwuwymiarowych.
wide_df = px.data.medals_wide()
fig = px.bar(wide_df, x="nation", y=["gold", "silver", "bronze"], title="Dane w formacie wide")
fig.show()
Zobaczmy jak wyglądają dane w formacie wide
:
wide_df
Kolorowane słupki¶
Wykres słupkowy można dostosować za pomocą argumentów słów kluczowych, na przykład w celu użycia koloru ciągłego, jak poniżej, lub koloru dyskretnego, jak powyżej.
df = px.data.gapminder().query("country == 'Poland'")
fig = px.bar(df, x='year', y='pop',
hover_data=['lifeExp', 'gdpPercap'], color='lifeExp',
labels={'pop':'ludność w Polsce'}, height=400)
fig.show()
df = px.data.gapminder().query("continent == 'Oceania'")
fig = px.bar(df, x='year', y='pop',
hover_data=['lifeExp', 'gdpPercap'], color='country',
labels={'pop':'population of Canada'}, height=400)
fig.show()
Stos vs grupowane słupki¶
Gdy kilka wierszy ma tę samą wartość x (tutaj Kobieta lub Mężczyzna), prostokąty są domyślnie ułożone jeden na drugim.
df = px.data.tips()
fig = px.bar(df, x="sex", y="total_bill", color='time')
fig.show()
Domyślne zachowanie skumulowanego wykresu słupkowego można zmienić na zgrupowane (znane również jako klastrowane) za pomocą argumentu barmode:
df = px.data.tips()
fig = px.bar(df, x="sex", y="total_bill",
color='smoker', barmode='group',
height=400)
fig.show()
Grupowanie wykresów słupkowych¶
Użycie argumentów słowa kluczowego facet_row
(lub facet_col
), utworzy nam grupowane subploty, w których różne wiersze (lub kolumny) odpowiadają różnym wartościom kolumny ramki danych określonej w facet_row
.
df = px.data.tips()
fig = px.bar(df, x="sex", y="total_bill", color="smoker", barmode="group",
facet_row="time", facet_col="day",
category_orders={"day": ["Thur", "Fri", "Sat", "Sun"],
"time": ["Lunch", "Dinner"]})
fig.show()