17.6 Pozicování

V ggplotu2 existuje hned několik způsobů, jak je možné ovlivnit pozici vykresleného geomu (tj. geometrického objektu reprezentujícího data) na stránce. První možností bylo použití škál – například jejich logaritmická transformace.

ggplot2 však v tomto ohledu nabízí mnohem více možností. Místem kde začít hledat je parametr position ve funkci layer(). Smyslem jeho použití je předejít překryvu pozorování ve výsledném obrázku. Parametr může nabývat následujících hodnot:

  • identity…je základní volba pro většinu funkcí geom_*(). Prakticky znamená, že z hlediska modifikace pozice geomu předává instrukci “nedělej nic a kresli na skutečnou pozici”.
  • jitter…ke skutečné pozici přidává náhodnou chybu
  • dodge…geomy skládá vedle sebe
  • stack…staví komínky – skládá geomy nad sebe
  • nudge…u překrývajících se geomů přidává ke skutečné pozici definovanou vzdálenost na ose x a y
  • jitterdodge…kombinuje jitter a dodge

V následujícím textu jsou blíže ukázány nejčastěji používané varianty změny pozic: jitter, dodge, stack a navíc poněkud specifická varianta fill. Varianty nudge a jitterdodge jsou specifické pro určité méně geomy a jejich přímé volání je v podstatě výjimečné.

17.6.1 jitter

position = "jitter" je populární volba zejména u bodových grafů, ve kterých je velký problém s overplottingem. Toto použití je tak typické, že existuje dokonce speciální geom_*() funkce: geom_jitter(). Ta je ekvivalentní k geom_point(position = "jitter").

geom_jitter() přidává ke skutečné pozici pozorování náhodnou složku, která je generovaná z uniformního rozdělení:

xtable %>% 
    ggplot(
        aes(x = x, y = y)
    ) +
    geom_jitter(color = "red") +
    geom_point()

V obrátku vidíte skutečnou pozici pozorování vykreslenou pomocí geom_point() a červené tečky ukazující posunuté hodnoty vykreslené pomocí geom_jitter(). Protože je chyba náhodná, bude obrázek při každém vykreslení vypadat jinak.

Pomocí parametrů width a height je možná nastavit šířku a výšku obdélníku, ve kterém se posunutá pozorování budou nacházet. Protože se náhodná složka generuje z uniformního rozdělení, je každý posun stejně pravděpodobný. Skutečná pozorovaná hodnota je pak právě ve středu obdélníku. To ilustruje následující obrázek:

xtable2 <- data_frame(
    x = rep(1:2,1000),
    y = rep(1:2,1000)
)
xtable2 %>% 
    ggplot(
        aes(x = x, y = y)
    ) +
    geom_jitter(
        alpha = 0.05,
        color = "red"
        ) +
    geom_point()

Posunutá pozorování (červené tečky) tvoří mračno rovnoměrně vyplňující celý obdélník za pozorovanou hodnotou (černá tečka), která je přesně v jeho středu.

17.6.2 stack

Typické použití této změny této modifikace pozice je u sloupcových grafů. Ty se v ggplot2 tvoří pomocí geom_bar() a jejich základní nestavení je, že mají být použity k vykreslení rozdělení diskrétní proměnné.

Pro použití geom_bar() vytvoříme novou tabulku occupation:

occupation <- data_frame(
    sex = rep(c("male","female"),100),
    occupation = sample(c("A","B","C","D"), 200, replace = TRUE, prob = abs(rnorm(4))),
    age = sample(c("old","young"), 200, replace = TRUE)
)

Tabulka obsahuje povolání (A, B, C nebo D), pohlaví a věkovou kohortu 200 lidí. Zajímá nás rozdělení povolání ve vzorku:

occupation %>% 
    ggplot(
        aes(x = occupation)
    ) +
    geom_bar()

geom_bar() v základním nastavení, tedy se stat = "count", provádí statistickou transformaci dat. Zjistí absolutní četnost jednotlivých variant proměnné v estetice x a tyto četnosti následně vykreslí formou sloupcového grafu.

Obrázek momentálně nijak nezohledňuje pohlaví, ale to se dá změnit. Lze ho namapovat například (a typicky) na estetiku fill:

occupation %>% 
    ggplot(
        aes(x = occupation, fill = sex)
    ) +
    geom_bar()

Ve výsledku dodá statistická transformace provedená stat_count() pro každé povolání dvě hodnoty: počet mužů a počet žen. Ty by se v logicky měly kreslit přes sebe – patří v obrázku na jedno místo. Očekávali bychom tedy tento obrázek:

Takový obrázek však není příliš užitečný, protože poskytuje spolehlivou informaci pouze o maximálních hodnotách. Proto již v základním nastavení geom_bar() používá position = "stack, která počet žen a mužů postaví nad sebe – do jednoho komínku.

Poznámka: “Špatný” obrázek můžete vykreslit s geom_bar(position = "identity).

17.6.3 dodge

Dalším typickým řešením u sloupcových grafů je vykreslení hodnot vedle sebe. Tento způsob čtenáři lépe předává informaci o počtu mužů a žen napříč povoláními. Horizontální posunutí sloupců zajišťuje position = "dodge":

occupation %>% 
    ggplot(
        aes(x = occupation, fill = sex)
    ) +
    geom_bar(position = "dodge")

17.6.4 fill

Poněkud specifickou úpravou pozice je fill, která upravuje nejen pozici, ale vlastně provádí i další statistickou transformaci. Nevrací totiž absolutní, ale relativní četnost:

occupation %>% 
    ggplot(
        aes(x = occupation, fill = sex)
    ) +
    geom_bar(position = "fill")

17.6.5 Facetování: na půli cesty mezi grupováním a pozicováním

Výše popsané pozicování mělo pozici geomů vlastně v rámci jednoho obrázku. Facetování k problému přistupuje jinak – rozlamuje původně jeden obrázek na více dílčích obrázků (facet). ggplot2 umožňuje vytvářet buď matice dílčích obrázků pomocí facet_grid() nebo prosté rozlomení do více obrázků pomocí facet_wrap().

Nejjednodušší příklad je použití facet_wrap(). Řekněme, že budeme chtít rozdělit obrázek s rozdělením povolání podle pohlaví:

occupation %>% 
    ggplot(
        aes(x = occupation)
    ) +
    geom_bar() -> p

p + facet_wrap("sex")

facet_wrap() rozdělil celkový obrázek na dva dílčí podle hodnot proměnné sex. Ta je v příkladu určena svým jménem (character). Další možností je její určení pomocí jednostranné rovnice (formula, blíže viz přednáška o ekonometrii v R):

p + facet_wrap(~ sex)

Vytvářet dílčí obrázky lze i podle kombinace více proměnných – můžeme chtít například samostatné dílčí obrázky pro kombinaci pohlaví a věku. V tomto případě se pro specifikaci proměnných použije vektor jejich jmen:

p + facet_wrap(c("sex","age"))

Nebo alternativně:

p + facet_wrap(~ sex + age)

Použít pro tyto aplikace facet_wrap() je možné, ale často je vhodnější sáhnout po facet_grid(), který je přímo navržen pro rozlomení obrázku podle kombinace více proměnných. facet_grid() vyžaduje specifikaci facetování pomocí objektu třídy formula:

p + facet_grid(sex ~ age)

Na levé straně rovnice (na levé straně ~) je proměnná (nebo jejich kombinace spojená +), která má tvořit řádky a na levé straně je proměnná nebo jejich kombinace, která má tvořit sloupce.

Funkce vytvářející facetování mají i další užitečné parametry. Pro facet_wrap() jsou specifické parametry ncol a nrow, které určují formát výstupní tabulky dílčích obrázků – kolik má mít sloupců a kolik řádků. Stačí přitom zadat jen jeden z těchto parametrů:

p + facet_wrap(c("sex","age"), nrow = 1)

Užitečný, ale pro správné čtení dat velmi ošemetný, parametr je scales. Ten umožňuje uvolnit škály v jednotlivých dílčích obrázcích. Základní hodnotou je fixed. V tomto případě jsou měřítka na všech dílčích obrázcích stejná. Varianty free, free_y a free_x umožňují uvolnit měřítka na všech osách nebo jen na ose x popřípadě y:

p + facet_wrap(c("sex","age"), nrow = 1, scales = "free_y")

Příklad ilustruje, že uvolnění os může být pro čtenáře velmi zavádějící. Stejná výška sloupce totiž v různých dílčích obrázcích znamená jinou pozorovanou hodnotu.