6 Grafy a vizualizace
Grafy a vizualizace jdou dělat v R mnoha způsoby. Něco je už v základním R a k tomu jsou stovky různých balíčků. Já ale používám skoro na všechno balíček ggplot2, který patří k nejpopulárnějším.
Upřímně, ggplot2 je dost komplikovaný, umí toho strašně moc a mě se nechce to všechno podrobně vysvětlovat. Vlastně by to ani nebylo v souladu se záměrem knížky, protože vás mám naučit hlavně to, co jde i v Excelu. A Excel, pokud jde o grafy, umí jen pár procent toho co ggplot2.
Takže spíš než teoretický výklad vám ukážu několik nejtypičtějších příkladů. Nebudu je podrobně vysvětlovat, takže buď je jenom podle svých potřeb opisujte (i s tím si vystačíte dost dlouho), nebo si ggplot2 důkladněji nastudujte z jiných zdrojů.
Připojím knihovnu (ve skutečnosti není třeba, je už v tidyverse) a dáme se do toho.
library(ggplot2)
6.1 Histogram
Histogram vám rychle ukáže rozložení kontinuálních (číselných) hodnot. Bývá prvním grafem, na který se u takového typu dat dívám.
V minulé kapitole jsme pracovali s datasetem starwars, tak u něj ještě chvíli zůstanu. Např. mě zajímá rozložení výšky postav:
|>
starwars ggplot(aes(x = height)) +
geom_histogram()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## Warning: Removed 6 rows containing non-finite values (stat_bin).
Ani to nebolelo, co?
Funkci ggplot
můžu kombinovat i s libovolnou předešlou manipulací dat. Takže kdybych chtěl jen rozložení výšky lidí, udělám to takhle:
|>
starwars filter(species == "Human") |>
ggplot(aes(x = height)) +
geom_histogram()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## Warning: Removed 4 rows containing non-finite values (stat_bin).
6.2 Scatter plot neboli bodový graf
Scatter plot pomáhá odhalit korelace mezi kontinuálními proměnnými. Souvisí například výška s váhou postavy? Abych to zjistil, Vyrobím scatter plot, ve kterém na jednu osu vynesu výšku a na druhou váhu.
|>
starwars ggplot(aes(x = height, y = mass)) +
geom_point()
## Warning: Removed 28 rows containing missing values (geom_point).
Z toho moc nepoznám, co? Je to tím, že jedna postava vahou výrazně vybočuje. Tak ji předem odfiltruju (operátor !=
znamená nerovnost):
|>
starwars filter(mass != max(mass, na.rm = TRUE)) |>
ggplot(aes(x = height, y = mass)) +
geom_point()
To už je lepší. Korelace sice není úplně pravidelná, není moc lineární, ale nějaká tam je – vyšší postavy jsou většinou i těžší.
To jde ukázat i tím, že nad vrstvu puntíků položím ještě vrstvu trendu. Vrstvení víc grafů přes sebe umí ggplot
krásně.
|>
starwars filter(mass != max(mass, na.rm = TRUE)) |>
ggplot(aes(x = height, y = mass)) +
geom_point() +
geom_smooth()
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'
A šlo by zkusit i lineární trend:
|>
starwars filter(mass != max(mass, na.rm = TRUE)) |>
ggplot(aes(x = height, y = mass)) +
geom_point() +
geom_smooth(method = lm)
## `geom_smooth()` using formula 'y ~ x'
6.3 Sloupečky
Další populární graf je sloupcový. Ukazuje obvykle číselnou (kontinuální) proměnnou vůči kategorické (resp. diskrétní). Zobrazím jím průměrnou výšku deseti nejvyšších druhů postav.
|>
starwars group_by(species) |>
summarise(height = mean(height, na.rm = TRUE)) |>
slice_max(order_by = height, n = 10) |>
ggplot(aes(x = height, y = species)) +
geom_col()
Není to setříděné, co? Není, protože ggplot
automaticky třídí hodnoty na osách, takže na ose y setřídí druhy podle abecedy. Jde to ale napravit funkcí fct_reorder
, kterou řeknu, že se mají druhy setřídit podle výšky:
|>
starwars group_by(species) |>
summarise(height = mean(height, na.rm = TRUE)) |>
slice_max(order_by = height, n = 10) |>
ggplot(aes(x = height, y = fct_reorder(species, height))) +
geom_col()
Teď je ale zas dost ošklivý název osy y, takže i ten opravím:
|>
starwars group_by(species) |>
summarise(height = mean(height, na.rm = TRUE)) |>
slice_max(order_by = height, n = 10) |>
ggplot(aes(x = height, y = fct_reorder(species, height))) +
geom_col() +
labs(x = "výška v cm", y = "druh", title = "Průměrná výška 10 nejvyšších druhů")
6.4 Čarový graf a timeline
Čárový graf se nejčastěji používá na vývoj něčeho v čase, takže si na demonstraci půjčím dataset economics
, který je k balíčku ggplot2 přibalený. Obsahuje mj. populaci USA v tisících za jednotlivé měsíce od července 1967 do dubna 2015.
Z těchto údajů vykreslený graf vypadá takhle:
|>
economics ggplot(aes(x = date, y = pop)) +
geom_line()
6.5 Boxplot
Hned na začátku jsem ukazoval histogram, který zobrazuje rozdělení hodnot. Když ale chcete vzájemně porovnat rozdělení ve více kategoriích, třeba v datasetu starwars
porovnat výšku lidí a droidů, mnohem lépe se na to hodí boxplot. Ten vypadá takhle:
|>
starwars filter(species %in% c("Human", "Droid")) |>
ggplot(aes(x = species, y = height)) +
geom_boxplot()
## Warning: Removed 5 rows containing non-finite values (stat_boxplot).
Z grafu jde vyčíst, že droidi mají mnohem větší rozptyl výšek (celá výška grafu včetně fousů) než lidé. Zároveň mají velmi nízko posazený medián (vodorovná čára uvnitř obdélníku) a jejich střední polovina (druhý a třetí kvartil; celý obdélník) je nižší než střední polovina lidí. Nejvyšší droid je ale podobně vysoký jako nejvyšší člověk (konec horního fousu).
6.6 Koláčový graf
V základním R jakýsi primitivní koláč je a ggplot2 ho umí taky. Jednak je to ale dost porod a jednak ho my, analytici, skoro nepoužíváme, protože to je takový vizualizační antipattern. Raději místo koláčů používejte sloupečky, např. takto:
|>
starwars count(species) |>
drop_na() |>
slice_max(order_by = n, n = 5, with_ties = FALSE) |>
ggplot(aes(x = TRUE, y = n / sum(n) * 100, fill = fct_reorder(species, n))) +
geom_col() +
geom_text(
aes(label = paste0(round(n / sum(n) * 100, 2), "%")),
position = position_stack(vjust = 0.5)
+
) scale_x_discrete(labels = NULL, breaks = NULL) +
labs(x = NULL, y = "podíl druhů v %", fill = "druhy") +
scale_fill_brewer(palette = "Set3")
Graf jsem schválně trochu vyšperkoval, přidal čísla, změnil barevnou paletu apod., takže kód je složitější, než by být musel.
6.7 Tahák
Stejně jako pro datové manipulace pomocí balíčku dplyr, existuje i pro grafy pomocí balíčku ggplot2 výborný tahák. A najdete ho i off-line přímo v RStudiu v menu help.
Kromě toho doporučuju tenhle vzorník nejčastějších grafů.