V předchozích dvou kapitolách jsme si představili, jak transformovat a sumarizovat proměnné. Vždy jsme však pracovali maximálně s jednou nebo dvěma proměnnými najednou. V praxi ovšem nejsou neobvyklé situace, ve kterých je nutné aplikovat určitou funkci na desítky, ne-li stovky proměnných najednou. Naštěstí pro nás, Tidyverse pro tyto příložitosti nabízí funkci across().
16.1 Transformace většího množství proměnných
Dataset countries obsahuje několik kategoriálních proměnných, mezi nimi postsoviet, eu_member, maj_belief a di_cat. Všechny tyto proměnné jsou typu character, pro analýzu by ovšem bylo lepší je převést na typ factor (pro typy objektů viz Kapitola 4).
Jednou možností je aplikovat funkci as.factor() na každou proměnnou zvlášť:
# A tibble: 5 × 4
postsoviet eu_member maj_belief di_cat
<fct> <fct> <fct> <fct>
1 no yes catholic Flawed democracy
2 yes yes orthodox Flawed democracy
3 yes yes nonbelief Flawed democracy
4 no yes protestantism Full democracy
5 yes yes catholic Full democracy
Tímto kódem dosáhneme našeho cíle, nejedná se však o nejelegantnější řešení, jelikož opakovaně aplikujeme stejnou funkci na každou z proměnných zvlášť. To nejen náš kód prodlužuje, ale zároveň zvyšuje šanci, že na některém řádku uděláme chybu. Alternativou je funkce across():
# A tibble: 5 × 4
postsoviet eu_member maj_belief di_cat
<fct> <fct> <fct> <fct>
1 no yes catholic Flawed democracy
2 yes yes orthodox Flawed democracy
3 yes yes nonbelief Flawed democracy
4 no yes protestantism Full democracy
5 yes yes catholic Full democracy
Funkce across() má dva nezbytné argumenty. Prvním z nich je .col, pomocí kterého specifikujeme proměnné, na které chceme naši funkci aplikovat. Argument .fns poté specifikuje funkci samotnou. Výsledek je stejný jako v předchozím případě, náš kód je ale kompaktnější.
Tímto ovšem výhody funkce across() nekončí. Proměnné je v ní možné specifikovat nejen tím, že je vyjmenuje jednu po druhé, ale i pomocí pomocných funkcí, se kterými jsme se již setkali v kapitole věnované výběrů sloupců (Sekce 10.2).
Pokud bychom například chtěli zaokrouhlit všechny numerické proměnné v datasetu na dvě desetinná místa, není nutné jejich názvy vypisovat ručně. Stačí využít kombinace funkcí where() a is.numeric():
countries %>%mutate(across(.cols =where(is.numeric),.fns = round, 2)) %>%select(where(is.numeric)) %>%head(5)
Warning: There was 1 warning in `mutate()`.
ℹ In argument: `across(.cols = where(is.numeric), .fns = round, 2)`.
Caused by warning:
! The `...` argument of `across()` is deprecated as of dplyr 1.1.0.
Supply arguments directly to `.fns` through an anonymous function instead.
# Previously
across(a:b, mean, na.rm = TRUE)
# Now
across(a:b, \(x) mean(x, na.rm = TRUE))
V rámci across() je také možné specifikovat argumenty pro aplikovanou funkci. Výše jsem určili, že numerické proměnné mají být zaoukrouhlené na dvě desetinná místa pomocí .fns = round, 2, kde 2 je argument funkce round(). Alternativně bychom mohli využít takzvanou tilda notaci (tilde notation):
countries %>%mutate(across(.cols =where(is.numeric),.fns =~round(., 2))) %>%select(where(is.numeric)) %>%head(5)
Na rozdíl od předchozího příkladu, funkci round() zde předchazí tilda (~) a prvním argumentem je .. Tato tečka (.) slouží jako placeholder pro proměnné dosazované do funkce round(). Jinak řečeno, funkce across() postupně dosadí každou proměnnou specifikovanou pomocí argumentu .cols na místo placeholderu .. Tilda notace je o něco komplexnější, než předchozí způsob, je ale o mnoho flexibilnější, protože nám umožňuje kontrolovat, do kterého argumentu budou námi proměnné dosazeny.
16.2 Sumarizace většího množsví proměnných
Funkci across() je možné aplikovat v rámci summarise() identicky jako v případě mutate(). Toho využijeme primárně pro výpočet deskriptivních statistik. Stejně jako v předchozích kapitál, i zde můžeme můžeme funkce navazovat na sebe:
# A tibble: 1 × 9
gdp population area life_exp uni_prc poverty_risk material_dep hdi
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 484601. 16754743 156019. 79.6 0.29 0.24 0.18 0.87
# ℹ 1 more variable: dem_index <dbl>
Všimněme si, že při výpočtu průměru numerických proměnných bylo nutné odstranit chybějící proměnné pomocí na.rm = TRUE (s tímto argumentem jsme se již setkali, viz Sekce 6.2). Všechny získané průměry jsme poté zaokrouhlili pomocí mutate().
Výsledkem jsou data v širokém formátu (Kapitola 12). Pro čitelnost bude lepší je převést do formátu dlouhého:
# A tibble: 2 × 10
eu_member gdp population area life_exp uni_prc poverty_risk material_dep
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 no 152949. 11949585. 1.45e5 78.6 0.27 0.31 0.26
2 yes 567514. 18299258. 1.60e5 79.9 0.3 0.23 0.17
# ℹ 2 more variables: hdi <dbl>, dem_index <dbl>
Výsledkem je dataframe, který sumarizuje numerické proměnné pro západní a postsovětské země zvlášť. Všimněme si, že při zaokrouhlování je nutné funkci round() aplikovat na všechny proměnné s vyjímkou proměnné eu_member.
Stejně jako v předchozí sekci, i zde je pro čitelnost lepší převést data do dlouhého formátu. Výsledkem bude dataset vhodný pro vizualizaci nebo statistické modelování:
# A tibble: 18 × 3
eu_member variable mean
<chr> <chr> <dbl>
1 no gdp 152949.
2 no population 11949585.
3 no area 144874.
4 no life_exp 78.6
5 no uni_prc 0.27
6 no poverty_risk 0.31
7 no material_dep 0.26
8 no hdi 0.84
9 no dem_index 6.87
10 yes gdp 567514.
11 yes population 18299258.
12 yes area 159999.
13 yes life_exp 79.9
14 yes uni_prc 0.3
15 yes poverty_risk 0.23
16 yes material_dep 0.17
17 yes hdi 0.88
18 yes dem_index 7.89
Na rozdíl od počítače, lidským čtenářům tento formát zpravdila nepřijde příliš přirozený. Ideálně proto data převedeme zpět do širšího formátu, abychom mohli jednoduše porovnat, která skupina zemí si vede lépe:
16.4 Sumarizace více proměnných bez použití across()
Přestože je kombinace funkcí summarise() a across() velmi užitečná, výsledný dataset není vždy ve formátu, se kterým je jednoduché dále pracovat, zvláště pokud aplikujeme více než jednu funkci najednou. Existuje ovšem trik, využívající převedu mezi širokým a dlouhým formátem, kterým si můžeme práci ulehčit.
Naším cílem může být spočítat průměr, směrodatnou odchylku, maximum a minimum všech numerickách proměnných. Jednou variantou je aplikovat funkci across() a specifikovat více funkcí pomocí lst(). Tato funkce umožňuje aplikovat několik funkcí v rámci jednoho across() Výsledek ovšem není příliš vzhledný:
countries %>%summarise(across(.cols =where(is.numeric),.fns =lst(mean, sd, min, max), na.rm =TRUE))
Výsledek není nepoužitelný, abychom se ovšem dostali k čitelné tabulce, museli bychom několikrát využít převodu mezi širokým a dlouhým formátem.
Alternativním způsobem je vybrat proměnné, se kterými chceme pracovat, převést data do dlouhého formátu a poté již aplikovat klasickou funkci summarise(). Nakonec jen výsledky zaokrouhlíme: