17.2 Základní vizualizace: vrstva po vrstvě

Celkovou konstrukci obrázku můžeme ilustrovat na tabulce diamonds, která je součástí balíku ggplot2. Tabulka obsahuje informace o jednotlivých kamenech (viz ?diamonds). Tabulka obsahuje přes 50 tisíc pozorování. Jejich vykreslování by zejména na pomalejších počítačích trvalo velmi dlouho. Proto budeme pracovat pouze s 500 náhodně vybranými řádky:

diamonds <- diamonds %>% sample_n(500)
print(diamonds)
## # A tibble: 500 x 10
##    carat cut       color clarity depth table price     x     y     z
##    <dbl> <ord>     <ord> <ord>   <dbl> <dbl> <int> <dbl> <dbl> <dbl>
##  1 1.28  Ideal     F     VVS2     62.2    56 12958  6.95  6.91  4.32
##  2 0.32  Premium   F     VVS1     60.7    58  1235  4.4   4.43  2.68
##  3 0.570 Very Good E     SI2      59.7    57  1244  5.4   5.48  3.25
##  4 0.6   Ideal     I     SI1      62.1    55  1390  5.39  5.42  3.35
##  5 1.05  Ideal     E     VS2      61.7    55  9624  6.54  6.55  4.04
##  6 1.7   Good      G     SI1      58.2    64 11180  7.89  7.85  4.58
##  7 1     Premium   E     VS2      62.7    59  6600  6.31  6.38  3.98
##  8 0.72  Premium   D     SI2      60.3    58  2484  5.81  5.76  3.49
##  9 0.54  Premium   F     SI1      60.4    58  1555  5.29  5.2   3.17
## 10 0.45  Ideal     G     VVS2     61.8    57  1181  4.94  4.9   3.04
## # … with 490 more rows

Našim cílem je vytvořit podobný obrázek, který byl použit pro schématickou ilustraci fungování ggplot2: Vykreslit závislost ceny (price), váhy (carat) a kvality řezu (cut).

Základ každého obrázku vytvoříme pomocí funkce ggplot():

ggplot(data = NULL, mapping = aes())

Funkce má dva základní argumenty: data obsahují tabulku s daty, která se mají vizualizovat. Parametr mapping pak přijímá základní pravidla, podle kterých se má vizualizace řídit. Přesněji řečeno pravidla vytvořená funkcí aes(), která určují, jaká proměnná se má mapovat na kterou estetiku.

Pro pochopení těchto pojmů je užitečné zamyslet se nad tím, jak vlastně funguje bodový graf. Jeho podstatou je to, že jedno pozorování, je reprezentováno jedním bodem. Jaké vlastnosti (estetiky) však tento bod může mít?

  1. Pozici v rovině obrázku: souřadnice na ose x (x) a y (y)
  2. Tvar (shape): kolečko, čtvereček, srdíčko, listy, káry,…
  3. Velikost (size)
  4. Barvu (color/colour)
  5. Barvu výplně (fill)
  6. Typ ohraničující linky (stroke)
  7. Průhlednost (alpha)

Všechny estetiky je možné nastavit (set) nebo namapovat (map). V případě nastavení bude estetika u všech pozorování stejná. V případě namapování se hodnota estetiky bude řídit podle hodnoty přiřazené proměnné.

Pokud tedy chceme vykreslit bodový graf závislosti, ceny a váhy, potom tyto proměnné chceme namapovat na vybrané estetiky. Stejného výsledku jako u úvodního obrázku dosáhneme pomocí aes(x = carat, y = price). Základní volání ggplot() tedy může vypadat následovně:

diamonds %>% 
    ggplot(
        aes(x = carat, y = price)
    )

Výsledkem je prázdná formátované plocha. Volání ggplot() totiž pouze vytvoří prázdné “plátno”, na které je potřeba přidávat jednotlivé vrstvy s obsahem.

Nové vrstvy se typicky přidávají voláním funkcí geom_*(). Tyto funkce nejsou nic jiného, než aliasy pro různé nastavení funkce layer():

layer(geom = NULL, stat = NULL, data = NULL, mapping = NULL,
  position = NULL, params = list(), inherit.aes = TRUE,
  check.aes = TRUE, check.param = TRUE, subset = NULL, show.legend = NA)

Funkce layer() má mnoho parametrů. Zásadní jsou tyto:

  • data…tabulka s daty, která se má použít v dané vrstvě. Pokud tento parametr není zadán, potom se použije tabulka dat specifikované ve volání ggpplot(). Každá vrstva tak může pracovat s jinými daty. (A také ggplot() nemusí obsahovat specifikaci dat.)
  • geom…typ geometrického objektu, který se má použít pro vizualizaci dat. Může se jednat o bod (point), polygon (polygon), úsečku (line) a mnoho dalších.
  • mapping…obsahuje namapování proměnných na estetiky pomocí funkce aes(). Pokud není parametr specifikován, potom se použije specifikace z ggplot(). Pokud je specifikace v konfliktu se specifikací v ggplot(), potom se použije specifikace z layer(). Pokud je specifikována estetika, která není přiřazena v ggplot(), potom se použije jako doplnění ke specifikaci z ggplot().
  • stat…statistická transformace dat, která se má provést před vykreslením. Vykreslují se až transformované data.
  • position…umožňuje upravit pozici hrubých dat před jejich vykreslením

Funkce layer() není zpravidla nikdy volána přímo. V podstatě vždy se používají funkce geom_*(). Pokud například chceme přidat vrstvu s bodovým grafem, potom použijeme geom_point(). Tato funkce je přesným ekvivalentem volání:

layer(
  data = NULL,
  mapping = NULL,
  geom = "point",
  stat = "identity",
  position = "identity"
)

Pokračujme v příkladu konstrukcí bodového grafu:

diamonds %>% 
    ggplot(
        aes(x = carat, y = price)
    ) +
    geom_point()

Vrstvu obsahující body jsme vytvořili voláním funkce geom_point(). Tato nová vrstva je k původnímu volání ggplot() připojena funkcí +. Pomocí této funkce můžeme do obrázku přidávat další vrstvy – například vrstvu, která vykreslí proloženou křivku:

diamonds %>% 
    ggplot(
        aes(x = carat, y = price)
    ) +
    geom_point() +
    geom_smooth()
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

Jak vlastně funguje ggplot2 vevnitř? Základní volání ggplot() vytvoří “prázdnou” datovou strukturu. Funkce + potom R říká, že má tuto datovou strukturu modifikovat. Jakým způsobem se to má stát určuje funkce volaná za +. Například + geom_point() přidá k původní datové struktuře vrstvu s body, atd.

Primárním výsledkem volání ggplot() je tedy datová struktura. Tu můžeme přiřadit do proměnné:

p <- diamonds %>% 
    ggplot(
        aes(x = carat, y = price)
    ) +
    geom_point()

…a dále modifikovat…

p <- p + geom_smooth()

…nebo “vytisknout”:

p
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'