# Začneme iniciací prostředí.
library(tidyverse)
# pokud soubory neexistují lokálně - stahnout!
if (!file.exists('./data/potraviny.csv')) {
curl::curl_download("https://www.jla-data.net/sample/R4SU-potraviny.csv",
"./data/potraviny.csv")
}
# lokální soubor načíst
potraviny_csv <- readr::read_csv2("./data/potraviny.csv")
Grafický výstup – tidyverse / ggplot2
Základní grafická knihovna v rámci tidyverse
je ggplot2
. Zkratka gg představuje anglické Grammar of Graphics, dvojka na konci znamená, že se jedná o druhý pokus (první se neosvědčil).
Významný rozdíl proti zbytku tidyverse
představuje, že jednotlivé operace bloku ggplotu nejsou pospojovány pajpou (%>%
) ale sčítáním (+
).
Důvody jsou především historické (knihovna ggplot2 je starší, než koncept pajpy v erku).
Sčítání místo pajp má řadu důsledků, například to že řádky v bloku ggplot2
jsou komutativní, a tedy zpravidla nezávislé na pořadí (což pro pajpy v dplyr
neplatí).
Grammar of Graphics
Grafická gramatika představuje set pravidel, které staví obrázek ze základních kamenů:
- podkladových dat
- geometrických objektů (body, čáry, sloupce…)
- osy (spojité či diskrétní, převrácené či logaritmické)
- souřadnicových systémů (kartézský, polární, zeměpisný)
- popisků a titulků
- facetů (dílčích grafů)
- animace (v rozšířeních ggplotu)
Základy ggplotu
ggplot2
je obecný, a tedy složitý, nástroj. Má smysl začít s jednoduchými grafy, a ke složitějším se propracovat.
Základem volání je funkce ggplot
, které předáme jako argument dataset, a vnoříme funkci aes()
, která upravuje vzhled (estetiku, anglicky aesthetic) – typicky určí, jak namapovat osy a barvy. Dále je třeba přidat některý z geometrických objektů.
Estetiky, které je možné pro grafy definovat, jsou:
- souřadnice (x a y, ve speciálních případech théta = θ)
- barva (color – pro body a čáry jediná barva, pro polygony a koláče barva okraje)
- tvar (shape – pouze pro body)
- výplň (fill – pouze pro polygony a koláče)
- průsvitnost (alpha)
Pro začátek si připravíme data frame ročních průměrů ceny základních potravin – tedy piva a vína.
alkohol <- potraviny_csv %>% # vytvoříme objekt alkohol tak, že vezmeme potraviny a pak ...
filter(reprcen_txt %in% c("Jakostní víno bílé [0,75 l]", # vybereme pivo a víno, a pak...
"Pivo výčepní, světlé, lahvové [0,5 l]")) %>%
filter(uzemi_txt == "Česká republika") %>% # pouze celková čísla (bez regionů), a pak...
group_by(rok = lubridate::year(obdobiod), reprcen_txt) %>% # dopočteme rok, a pak ...
summarise(prumer = mean(hodnota))
V prvním ggplotu zadáme dataset (data = ...
) a v aes()
funkci nastavíme proměnné pro osy x a y. Doplníme funkci geom_point()
pro bodový graf.
ggplot(data = alkohol, aes(x = rok, y = prumer)) +
geom_point()
Graf má jednu velkou vadu – není poznat, které hodnoty představují pivo, a které víno.
Pro rozlišení musíme využít namapovat sloupec reprcen_txt
na některou z estetik. Smysl dávají dvě: tvar bodu (shape) a barva.
ggplot(data = alkohol, aes(x = rok, y = prumer, shape = reprcen_txt)) +
geom_point()
ggplot(data = alkohol, aes(x = rok, y = prumer, color = reprcen_txt)) +
geom_point()
Pokud se nám defaultní barvy nelíbí (což se může stát) tak upravíme paletu. Například na oblíbenou paletu paní Cynthie Brewer.
ggplot(data = alkohol, aes(x = rok, y = prumer, color = reprcen_txt)) +
geom_point() +
scale_color_brewer(palette = "RdYlBu")
Čáry z bodů uděláme záměnou geomu z point na line.
ggplot(data = alkohol, aes(x = rok, y = prumer, color = reprcen_txt)) +
geom_line() +
scale_color_brewer(palette = "RdYlBu")
Tlustší čáru získáme upřesněním šířky čáry (lwd = line width) v rámci geom_line()
.
ggplot(data = alkohol, aes(x = rok, y = prumer, color = reprcen_txt)) +
geom_line(lwd = 2) +
scale_color_brewer(palette = "RdYlBu")
Geom typu col zařídí sloupcový graf. Pozor, musíme také změnit barvu z color (znamená barvu okraje) na fill (znamená výplň).
Default pro sloupcový graf jsou sloupce na sobě.
ggplot(data = alkohol, aes(x = rok, y = prumer, fill = reprcen_txt)) +
geom_col() +
scale_fill_brewer(palette = "RdYlBu")
Sloupcový graf se sloupečky vedle sebe získáme upřesněním position = "dodge"
při volání geom_col()
ggplot(data = alkohol, aes(x = rok, y = prumer, fill = reprcen_txt)) +
geom_col(position = "dodge") +
scale_fill_brewer(palette = "RdYlBu")
Správný graf potřebuje nadpis; vytvoříme ho pomocí labs()
jako labels.
ggplot(data = alkohol, aes(x = rok, y = prumer, color = reprcen_txt)) +
geom_point() +
scale_color_brewer(palette = "RdYlBu") +
labs(title = "Vývoj cen")
Osy a legenda jsou defaultně nadepsány názvem proměnné; to jde opět změnit voláním labs()
.
ggplot(data = alkohol, aes(x = rok, y = prumer, color = reprcen_txt)) +
geom_point() +
scale_color_brewer(palette = "RdYlBu") +
labs(title = "Vývoj cen",
x = "Rok měření",
y = "Průměrná cena v Kč",
color = "Základní životní jistoty")
Graf, který nezačíná osu Y na nule si říká o malér. Rozsah osy Y natvrdo vynutíme uvedením horní a dolní meze do ylim()
; pro osu X by to bylo xlim()
.
ggplot(data = alkohol, aes(x = rok, y = prumer, color = reprcen_txt)) +
geom_point() +
scale_color_brewer(palette = "RdYlBu") +
labs(title = "Vývoj cen",
x = "Rok měření",
y = "Průměrná cena v Kč",
color = "Základní životní jistoty") +
ylim(0, 115)
Někomu může nevyhovovat šedé pozadí grafu. Odstraníme ho nastavením tématu – theme_*
. Zde theme_linedraw()
. Protože by světle žlutá nebyla na bílém pozadí vidět tak nastavíme barvy ručně.
ggplot(data = alkohol, aes(x = rok, y = prumer, color = reprcen_txt)) +
geom_point() +
scale_color_manual(values = c("Jakostní víno bílé [0,75 l]" = "goldenrod2",
"Pivo výčepní, světlé, lahvové [0,5 l]" = "cornflowerblue"))+
labs(title = "Vývoj cen",
x = "Rok měření",
y = "Průměrná cena v Kč",
color = "Základní životní jistoty") +
ylim(0, 115) +
theme_linedraw()
Často použijeme osu časovou, k tomu nám pomůže vánoční kapr. Je patrné, že zatímco cenu piva sledují statistici měsíčně, tak cenu kapra pouze před Vánoci.
Na časové ose je třeba upravit interval popisků (date_breaks
) a jejich formát; symbol %m
znamená číslo měsíce a %Y
čtyřmístný rok.
Abychom zpřehlednili překrývající se hodnoty, tak v geom_point()
nastavíme průhlednost (alpha
) a body mírně rozhážeme do stran (position = "jitter"
).
V obchodním prostředí často využijeme možnost osy s popisky měn. Slouží k tomu funkce dollar_format()
z knihovny scales
.
library(scales)
kapr <- potraviny_csv %>%
filter(reprcen_txt %in% c("Kapr živý [1 kg]", "Pivo výčepní, světlé, lahvové [0,5 l]")
& uzemi_txt != "Česká republika"
& obdobiod >= "2017-06-01"
& obdobiod <= "2018-12-31")
ggplot(kapr, aes(x = obdobiod, y = hodnota, color = reprcen_txt)) +
geom_point(alpha = 0.5, position = "jitter") +
scale_color_manual(values = c("goldenrod2", "cornflowerblue")) +
scale_x_date(date_breaks = "1 month", date_labels = "%m – %Y") + # rozteč a formát popisků
scale_y_continuous(limits = c(0, 115), # omezení hodnot (aby byla vidět nula)
labels = dollar_format(prefix = "", suffix = " Kč")) + # měnový formát popisků
labs(title = "Pivo a kapr",
x = "Měsíc měření",
y = "Průměrná cena",
color = "Základní životní jistoty") +
theme_linedraw() +
theme(axis.text.x = element_text(angle = 90)) # popisky na výšku, aby se vešly
Koláčové grafy se v erkových kruzích moc nenosí (obdobně jako grafy se dvěma osami) ale prostředí obchodu je občas vyžaduje.
V ggplotu2 jsou koláčové grafy implementované jako sloupcové grafy v polárních souřadnicích místo kartézských (tj. “zatočené do kolečka”). Zatímco karteziánské souřadnice jsou definovány dvěma vzdálenostmi (osa x a y), polární souřadnice jsou definovány vzdáleností a úhlem (théta), který je třeba namapovat v rámci volání coord_polar()
.
silvestr <- potraviny_csv %>%
filter(reprcen_txt %in% c("Kapr živý [1 kg]",
"Pivo výčepní, světlé, lahvové [0,5 l]",
"Jakostní víno bílé [0,75 l]")
& uzemi_txt == "Česká republika"
& obdobiod >= "2018-12-01"
& obdobido <= "2019-01-01")
ggplot(data = silvestr, aes(x = "", # souřadnice x se nepoužije (ale musí být)
y = hodnota, # cena jako hodnota
fill = reprcen_txt, # potravina jako barva
label = hodnota)) + # cena jako popisek
geom_col() + # sloupcový graf ...
coord_polar(theta = "y") + # ... zatočený do kolečka
geom_text(position = position_stack(vjust = 0.5)) + # popisky na střed
scale_fill_brewer(palette = "RdYlBu") + # barvičky paní Brewer
labs(title = "Vánoční spotřební koš", # název grafu
fill = "Základní potravina") + # název legendy
theme_void() # téma bez příkras
Mapovou vizualizaci vytvoříme tak, že data o ceně kapra v regionech připojíme k prostorovému objektu krajů České republiky. Tyto jsou k dispozici v package RCzechia
, která obsahuje administrativní regiony ČR od obcí přes ORP, okresy a kraje až k ČR jako celku, včetně klíčů do číselníků používaných statistickým úřadem.
Práce s mapami vyžaduje kromě RCzechia
také knihovnu sf
, která definuje objekty mapových vektorových dat a práci s nimi. Vždy je třeba připojovat data k mapě, ne mapu k datům.
Z grafu je se zdá, že cena kapra je úměrná vzdálenosti od Třeboně. To dává smysl.
library(sf) # umožňuje práci s prostorovými daty
library(RCzechia) # prostorová data ČR - obsahuje kraje()
kapr <- potraviny_csv %>% # přepíšeme objekt kapr tím, že vezememe potraviny, a pak..
filter(reprcen_txt %in% c("Kapr živý [1 kg]") # vybereme kapra,
& uzemi_txt != "Česká republika" # pouze regionální hodnoty (tj. ne ČR jako celek)
& lubridate::year(obdobido) == 2017) %>% # pouze hodnoty z roku 2017, a pak...
mutate(uzemi_kod = as.character(uzemi_kod)) # převedeme kód území z čísla na text (klíče RCzechia jsou text)
krajsky_kapr <- kraje("low") %>% # objekt krajsky_kapr vytvoříme tak, že vezmeme mapu krajů, a pak...
inner_join(kapr, by = c("KOD_KRAJ" = "uzemi_kod")) # k nim připojíme podle klíče objekt kapr
ggplot(data = krajsky_kapr, aes(fill = hodnota)) +
# geom_sf() ukazuje mapu; vyžaduje načtenou knihovnu sf
geom_sf() +
# geom_sf_text() nakreslí na mapě popisky
geom_sf_text(aes(label = round(hodnota)), color = "grey25") +
# škála barev od žluté po červenou, bez legendy (popisek stačí...)
scale_fill_gradient(low = "yellow", high = "firebrick2", guide = "none") +
labs(title = "Český kapr v roce 2017", # nadpis grafu
subtitle = "průměrná cena v Kč po krajích") + # podtitulek
theme_void() +
coord_sf(datum = NA)
Další čtení / reference
- Data Visualization cheatsheet od RStudia
- package ggplot2 dokumentace
- package scales dokumentace
- package RCzechia vignette
- Data Visualization kapitola R for Data Science