--- title: "Vesmír tidyverse" author: "Štěpán Mikula" documentclass: article output: pdf_document: default html_document: theme: cerulean toc: yes toc_float: yes fontsize: 10pt classoption: a4paper --- # Co je to tidyverse? *tidyverse* je soubor balíků obashujících všechny nástroje potřebné pro základní úkony v datové analýze. Balíky z *tidyverse* Vám umožní: - načíst data (balík *reader*, *haven*, *xml2*, *rvest* a další), - přeskládat je do požadované formy (balík *tidyr*), - modifikovat je (balík *dplyr*) - a vizualizovat (balík *ggplot2*). Součástí *tidyverse* jsou i další balíky. Některé z nich Vám jsou již známé (např. *purrr*, *stringr*, *forcats* nebo *tibble*). Všechny balíky v *tidyverse* sdílejí logiku ovládání a datové struktury. Dohromady tak poskytují uživateli dobře provázané, kooperující a moderní prostředí pro datovou analýzu. Nevýhodou *tidyverse* je, že jejich vývoj stále není zcela ukončen a dohcází v něm k zásadním změnám. Balíky z tidyverse je možné načítat jednotlivě podle potřeby, nebo načtením metabalíku *tidyverse*: ```r library(tidyverse) ``` ``` ## ── Attaching packages ────────────────────────────────────────────────────────────────────── tidyverse 1.3.0 ── ``` ``` ## ✓ ggplot2 3.3.1 ✓ purrr 0.3.4 ## ✓ tibble 3.0.1 ✓ dplyr 1.0.0 ## ✓ tidyr 1.1.0 ✓ stringr 1.4.0 ## ✓ readr 1.3.1 ✓ forcats 0.5.0 ``` ``` ## ── Conflicts ───────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ── ## x dplyr::filter() masks stats::filter() ## x dplyr::lag() masks stats::lag() ``` ## Práce s tidyverse ### Trubky/pipes S pomocí *tidyverse* je možné psát velmi dobře srozumitelný kód. Hadley Wickham, který stojí za vytvořením podstatné části *tidyverse*, při popisu balíků mluví o konceptu "gramatiky práce s daty" a "gramatice vizualizace dat". Průběh datové analýzy můžeme popsat jako sekvenci úkonů. Například: 1. Načti data. 1. Vezmi načtenou tabulku a vyber z ní několik sloupců. 1. Vezmi upravenou tabulku a vyber pouze řádky, které splňují určité podmínky. 1. Vezmi upravenou tabulku a na jejím základě vykresli obrázek. 1. Výsledek ulož do proměnné `x`. Každý krok přitom využívá výsledek kroku předchozího. Pro podobné řetezení kroků využívá *tidyverse* speciální funkci `%>%` (tzv. trubku/pipe), které spojuje dva kroky. Výstup prvního kroku vkládá jako vstup do následujícího kroku. Předchozí sekvenci kroků bychom tedy mohli schématicky zapsat následujícím způsobem: ```r x <- read_tsv() %>% # Načti data select() %>% # Vyber sloupce filter() %>% # Vyber řádky ggplot() # Vykresli data ``` Ukázka kódu není funkční -- funkce nemají zadané žádné parametry, ale ukazuje logiku celého přístupu. Výsledný kód svou strukturou připomíná strukturu psaného jazyka. Intrukce přehledně plyne zleva do prava, podobně jako text v knize. Bez použití funkce `%>%` by postup vypadal následovně: ```r x <- read_tsv() x <- select(x) x <- filter(x) x <- ggplot(x) ``` Výsledek by byl zcela identický (a provedení kódu u velkých tabulek o maličko rychlejší). Výhodou trubek je však čitelnost a přehlednost. Praxe ukazuje, že mít jasný a čístý kód je v praxi datové analýzy často důležitější než marginální ztráta rychlosti. V tomto kurzu budeme od této chvíle často používat funkci `%>%`. Pokud si oblíbíte používání trubek, můžete se podívat na balík `magrittr`, který kromě `%>%` implementuje i další trubkoidní funkce. #### Placeholder "." Funkce `%>%` ja nastavená tak, že obsah, který ji protéká vždy umisťuje do prvního parametru přijímající funkce. To je skoro vždy žádoucí chování, ale ne vždy. Modifikovat je ho možné s použítím symbolu `.`, který určuje místo, na které má trubka přenášený obsah umístit. Můžeme si například představit situaci, kdy máme vektory `x` a `w`. Chceme spočítát vážený průměr `x`, ale trubkou nám putuje vektor vah `w`. Požadovaného výsledku dosáhneme takto: ```r w %>% weighted.mean(x,.) ``` ### Subsetování *tidyverse*, konkrétně balík *dplyr* obsahuje funkce pro subsetování. Zběžně se nyní seznámí s funkcí `select()`, která slouží k výběru sloupců. Na jejím příkladě si ukážeme, jak se v *tidyverse* zachází se jmény sloupců. Základní syntaxe `select()` je triviální: ```r select(.data, ...) ``` Prvním parametrem je vstupní tabulka. V parametru `...` jsou specifikovány sloupce. Jako ukázkovou tabulku budeme používat `us_rent_income` z balíku *tidyr*: ```r us_rent_income ``` ``` ## # A tibble: 104 x 5 ## GEOID NAME variable estimate moe ## ## 1 01 Alabama income 24476 136 ## 2 01 Alabama rent 747 3 ## 3 02 Alaska income 32940 508 ## 4 02 Alaska rent 1200 13 ## 5 04 Arizona income 27517 148 ## 6 04 Arizona rent 972 4 ## 7 05 Arkansas income 23789 165 ## 8 05 Arkansas rent 709 5 ## 9 06 California income 29454 109 ## 10 06 California rent 1358 3 ## # … with 94 more rows ``` Poznámka: Speciální metody výběru sloupců jsou implementovány v balíku *tidyselect*, Ten si však nemusíte vždy loadovat. Balíky z *tidyverse* si vše vyřeší samy. #### Non-standard evaluation a identifikace jménem sloupce *tidyverse* používá tzv. nestandardní evaluaci. Ta je výhodná zvláště při interaktivní práci s daty. Praktickým dopadem je, že se jména sloupců píšou bez úvozovek. První možností jak identifikovat sloupec je tedy jménem bez úvozovek. Můžeme vybrat jeden: ```r us_rent_income %>% select(variable) ``` ``` ## # A tibble: 104 x 1 ## variable ## ## 1 income ## 2 rent ## 3 income ## 4 rent ## 5 income ## 6 rent ## 7 income ## 8 rent ## 9 income ## 10 rent ## # … with 94 more rows ``` Nebo více sloupců: ```r us_rent_income %>% select(variable,estimate) ``` ``` ## # A tibble: 104 x 2 ## variable estimate ## ## 1 income 24476 ## 2 rent 747 ## 3 income 32940 ## 4 rent 1200 ## 5 income 27517 ## 6 rent 972 ## 7 income 23789 ## 8 rent 709 ## 9 income 29454 ## 10 rent 1358 ## # … with 94 more rows ``` #### Identifikace pozicí Vedle jména je možné pro identifikaci sloupce použít číslo jeho pozice: ```r us_rent_income %>% select(1,2,4) ``` ``` ## # A tibble: 104 x 3 ## GEOID NAME estimate ## ## 1 01 Alabama 24476 ## 2 01 Alabama 747 ## 3 02 Alaska 32940 ## 4 02 Alaska 1200 ## 5 04 Arizona 27517 ## 6 04 Arizona 972 ## 7 05 Arkansas 23789 ## 8 05 Arkansas 709 ## 9 06 California 29454 ## 10 06 California 1358 ## # … with 94 more rows ``` #### Speciální funkce Funkce, které potřebují specifikaci sloupců umí pracovat se speciálními funkcemi, které budou fungovat pouze v jejich rámci. Základní speciální funkce jsou dvě: `-` a `:`. Funkce `-` umožňuje negativní výběr -- "vyber všechno až na". Následující volání funkce `select()` tak vrátí všechny sloupce až na `GEOID` a `NAME`: ```r us_rent_income %>% select(-GEOID,-NAME) ``` ``` ## # A tibble: 104 x 3 ## variable estimate moe ## ## 1 income 24476 136 ## 2 rent 747 3 ## 3 income 32940 508 ## 4 rent 1200 13 ## 5 income 27517 148 ## 6 rent 972 4 ## 7 income 23789 165 ## 8 rent 709 5 ## 9 income 29454 109 ## 10 rent 1358 3 ## # … with 94 more rows ``` Funkce `:` umožňuje specifikovat rozsah sloupců. To lze využít pokud chceme například vybrat sloupce `GEOID` a všechny sloupce mezi `variable` a `moe`: ```r us_rent_income %>% select(GEOID, variable:moe) ``` ``` ## # A tibble: 104 x 4 ## GEOID variable estimate moe ## ## 1 01 income 24476 136 ## 2 01 rent 747 3 ## 3 02 income 32940 508 ## 4 02 rent 1200 13 ## 5 04 income 27517 148 ## 6 04 rent 972 4 ## 7 05 income 23789 165 ## 8 05 rent 709 5 ## 9 06 income 29454 109 ## 10 06 rent 1358 3 ## # … with 94 more rows ``` Speciální funkce fungují i při identifikace sloupců jejich pozicí... ```r us_rent_income %>% select(-1,-2) ``` ``` ## # A tibble: 104 x 3 ## variable estimate moe ## ## 1 income 24476 136 ## 2 rent 747 3 ## 3 income 32940 508 ## 4 rent 1200 13 ## 5 income 27517 148 ## 6 rent 972 4 ## 7 income 23789 165 ## 8 rent 709 5 ## 9 income 29454 109 ## 10 rent 1358 3 ## # … with 94 more rows ``` ```r us_rent_income %>% select(1,3:5) ``` ``` ## # A tibble: 104 x 4 ## GEOID variable estimate moe ## ## 1 01 income 24476 136 ## 2 01 rent 747 3 ## 3 02 income 32940 508 ## 4 02 rent 1200 13 ## 5 04 income 27517 148 ## 6 04 rent 972 4 ## 7 05 income 23789 165 ## 8 05 rent 709 5 ## 9 06 income 29454 109 ## 10 06 rent 1358 3 ## # … with 94 more rows ``` ...a je možné je kombinovat ```r us_rent_income %>% select(-variable:-moe) ``` ``` ## # A tibble: 104 x 2 ## GEOID NAME ## ## 1 01 Alabama ## 2 01 Alabama ## 3 02 Alaska ## 4 02 Alaska ## 5 04 Arizona ## 6 04 Arizona ## 7 05 Arkansas ## 8 05 Arkansas ## 9 06 California ## 10 06 California ## # … with 94 more rows ``` #### Funkce pomocníčci: select helpers Balík *tidyselect* obshauje funkce, které umožňují identifikovat sloupce jinak než přímým zadáním jména nebo pozice: - `starts_with()` vybírá sloupce, jejichž jméno začíná na řetězec, který je argumentem funkce `starts_with()` - `ends_with()` vybírá sloupce, jejichž jméno končí na řetězec, který je argumentem funkce `ends_with()` - `contains()` vybírá sloupce, jejichž jméno obsahuje řetězec, který je argumentem funkce `contains()` - `matches()` vybírá sloupce, jejichž jméno odpovídá zadanému regulárnímu výrazu - `num_range()` slouží pro výběr sloupců, jejichž jméno je tvořeno kombinací řetězce a čísla -- například `trial_1`, `trial_2`,... - `one_of()` vrátí sloupce, jejichž jména jsou obsažena ve vektoru, který je vstupem funkce - `everything()` vrací všechny sloupce - `last_col()` vrací poslední sloupec Tyto funkce opět fungují jenom "uvnitř" kompatibilních funkcí. K subsetování se v mírně větším detailu vrátíme znovu v kapitole věnované balíku *dplyr*.