Obdobně jako je funkce select() neocenitelným pomocníkem pro práci se sloupci dataframů, její příbuzná filter() nám dobře poslouží pro filtrování řádků. Tato kapitola je věnována právě jí, ale také rodině funkcí slice() a funkci arrange().
11.1 Filtrování řádků
Pro filtrování řádků je třeba trocha výrokové logiky. Základními logickými operátory v R jsou == (EQUAL), | (OR) a & (AND). Nepřekvapivě, pro HIGHER THAN používám >=, naopak pro LOWER THAN slouží <=. Negace se provádí pomocí vykřičníku, tedy například NOT EQUAL je !=.
Vybaveni těmito znalostmi, filtrování řádků není obtížný úkol. Hlavní funkcí je zde filter():
filter(countries, postsoviet =="yes"& gdp >100000)
Podmínky filtrování lze kombinovat, například vyfiltrovat pouze postsovětské země s hrubým domácím produktem větším než 100 000 miliónů euro.
Tip%in% místo |
Občas je naším cílem vyfiltrovat řádky obsahující některou z vybraných hodnot kategoriální proměnné, například všechny náboženské skupiny spadající pod křesťanství. Jednou možností je:
Tento přístup funguje, je ale zbytečně květnatý. Místo něj je možné aplikovat operátor %in%, pomocí kterého můžeme vyfiltrovat všechny hodnoty objevující se ve zvoleném vektoru:
Oba tyto příkazy vedou ke stejnému výsledku, ten druhý je ale výrazně kompaktnější.
Zároveň se může stát, že je někdy jednodušší vyjmenovat hodnoty, které ve výběru nechceme, než ty, které tam chceme. I pro to existuje elegantní řešení, které využívá znak !, jehož význam v jazyce R je negace čili logické NOT. Například pokud bychom chtěli všechny země, které nemají jako majoritní některé z křesťanských nábožesntví:
Jak si jistě dokážete představit, funkce select() a filter() jsou často využívané dohromady:
countries %>%filter(postsoviet =="yes") %>%select(country, postsoviet, life_exp)
# A tibble: 16 × 3
country postsoviet life_exp
<chr> <chr> <dbl>
1 Bulgaria yes 74.8
2 Czechia yes 79.2
3 Germany yes 81
4 Estonia yes 77.8
5 Croatia yes 78.3
6 Latvia yes 75
7 Lithuania yes 75
8 Hungary yes 76
9 Poland yes 77.8
10 Romania yes 75.2
11 Slovenia yes 80.9
12 Slovakia yes 77.4
13 North Macedonia yes 75.9
14 Albania yes 76.4
15 Serbia yes 76.3
16 Bosnia and Herzegovina yes 77.3
11.2 Řezání dataframů
V některých případech budeme chtít filtrovat na základě pořadí řádků dataframů. K tomu nám poslouží rodina funkcí slice z balíčku dplyr.
Prvním členem této rodiny je funkce slice(). Její aplikace je velmi podobná klasickému indexování pomocí hranatých závorek. Například výběr prvního řádku v dataframu:
slice(countries, 1)
Je ekvivalentní countries[1, ] a vrátí první řádek dataframu. Obdobně podobné jsou i funkce slice(countries, -1) a countries[-1, ], které vrátí všechny řádky kromě prvního. Funkce slice() je však pouze základem pro řadu dalších užitečných funkcí.
Další dvě funkce, které nám již svým fungováním budou povědomé jsou slice_head() a slice_tail(). Ty, obdobně jako funkce head() a tail(), vrátí prvních n řádků v dataframů. Na rozdíl od svých příbuzných ze základní instalace R, ovšem slice funkce umožňují vybrat nejen absolutní, ale i relativní počet řádků. Například pro vybrání prvních deseti procent dataframu:
slice_head(countries, prop =0.1)
Pro vybrání absolutního počtu řádku slouží argument n.
O něco zajímavější jsou funkce slice_max() a slice_min(). Ty umožňují vybrat n řádků s nejvyšší, respektive nejnižší, hodnou dané proměnné. Pomocí těchto funkcí můžeme například jednoduše zjistit, které tři země v našem dataframu mají nejvyšší naději na dožití:
slice_max(countries, order_by = life_exp, n =3) %>%select(country, life_exp)
# A tibble: 3 × 2
country life_exp
<chr> <dbl>
1 Switzerland 83.3
2 Spain 83.1
3 France 82.9
a které naopak nejnižší:
slice_min(countries, order_by = life_exp, n =3) %>%select(country, life_exp)
# A tibble: 3 × 2
country life_exp
<chr> <dbl>
1 Bulgaria 74.8
2 Latvia 75
3 Lithuania 75
Funkce slice_max() a slice_min() jsme zde zkombinovali s funkcí select(), abychom vybrali jen relevantní proměnné.
Posledním členem rodiny je funkce slice_sample(), která vybere náhodné řádky dataframu. Tato funkce najde uplatnění zejména v simulačních studiích a technikách.
slice_sample(countries, n =3)
11.3 Podskupiny v datech
V tuto chvíli si možná někteří čtenáři říkají, jaké je využití slice funkcí oproti jejich klasickým variantám, jako je head() nebo tail(). Jednou z jejich předností je možnost kombinovat je s funkcionalitou by, což je možnost, jak můžeme různým funkcím z balíku dplyr přikázat, aby požadovanou operaci provedly zvlášť pro různé podskupiny.
Funkcionalita se vyvolá použitím argumentu by uvnitř funkce. Podskupiny jsou definované kategorickou proměnnou v dataframu. Tímto způsobem můžeme zjistit, nejen které země se těší nejvyšší naději na dožití obecně, ale i to, jak jsou na tom postsovětské a ostatní země zvlášť:
countries %>%slice_max(order_by = life_exp, n =3, by = postsoviet) %>%select(country, postsoviet, life_exp)
# A tibble: 6 × 3
country postsoviet life_exp
<chr> <chr> <dbl>
1 Switzerland no 83.3
2 Spain no 83.1
3 France no 82.9
4 Germany yes 81
5 Slovenia yes 80.9
6 Czechia yes 79.2
Zatímco mezi nepostsovětskými zeměmi vedou Švýcarsko, Španělsko a Francie, v postsovětské skupině je to Německo, Slovinsko a Česká republika. Třídit je možné i pomocí většího počtu proměnných, například pro třídění podle postsovětské historie a členství v Evropské unii takto:
countries %>%slice_max(order_by = life_exp, n =1, by =c(postsoviet, eu_member)) %>%select(country, postsoviet, eu_member, life_exp)
# A tibble: 4 × 4
country postsoviet eu_member life_exp
<chr> <chr> <chr> <dbl>
1 Spain no yes 83.1
2 Germany yes yes 81
3 Switzerland no no 83.3
4 Bosnia and Herzegovina yes no 77.3
Využití argumentu by ve spojení s funkcemi pro manipulaci s daty z balíku dplyr má široke využití, které bude dále ilustrováno v různých situacích.
Poznámka
Argument by byl představen teprve ve verzi dplyr 1.1.0 v roce 2023 jako alternativa pro do té doby používanou funkci group_by(). V jejím případě šlo na rozdíl od argumentu by o samostantou funkci, která dataset rozdělila na podskupiny typicky až do odvolání pomocí funkce ungroup(). Ve většině případů nám přijde vhodnější používat argument by, přestože varianta group_by() je také dále dostupná. Pro případ uvedený výše by fungovala takto:
countries %>%group_by(postsoviet, eu_member) |>slice_max(order_by = life_exp, n =1) %>%select(country, postsoviet, eu_member, life_exp) |>ungroup()
# A tibble: 4 × 4
country postsoviet eu_member life_exp
<chr> <chr> <chr> <dbl>
1 Switzerland no no 83.3
2 Spain no yes 83.1
3 Bosnia and Herzegovina yes no 77.3
4 Germany yes yes 81
Pokud bychom nepřipojili závěrečné ungroup() dostali bychom stejné hodnoty, výsledek by nicméně zůstal rozdělen na čtyři podksupiny i pro případné další operace.
11.4 Pořadí řádků
Posledním typem operace, kterou si v této kapitole představíme, je řazení řádků pomocí funkce arrange(). Pořadí zemí v dataframu countries podle naděje na dožití získáme jednoduše:
countries %>%arrange(life_exp) %>%select(country, life_exp)
# A tibble: 38 × 2
country life_exp
<chr> <dbl>
1 Bulgaria 74.8
2 Latvia 75
3 Lithuania 75
4 Romania 75.2
5 North Macedonia 75.9
6 Hungary 76
7 Serbia 76.3
8 Albania 76.4
9 Turkey 76.4
10 Montenegro 76.8
# ℹ 28 more rows
Při bližším pohledu zjistíme, že země jsou seřazený vzestupně. Nejhůře se vede Bulhrasko a Litva s Lotyšskem. Co kdyby nás ale zajímaly země s nejvyšší nadějí na dožití? Pro sestupné řazení zkombinujeme funkci arrange() se znaménkem -:
countries %>%arrange(-life_exp) %>%select(country, life_exp)
# A tibble: 38 × 2
country life_exp
<chr> <dbl>
1 Switzerland 83.3
2 Spain 83.1
3 France 82.9
4 Italy 82.8
5 Norway 82.5
6 Luxembourg 82.4
7 Sweden 82.4
8 Iceland 82.4
9 Austria 81.9
10 Netherlands 81.6
# ℹ 28 more rows
Nejvyšší naději na dožití se těší Švýcarsko, se Španělskem v těsném závěsu.
::: callout info Alternativně se lze setkat také s využitím funkce desc() ve smyslu anglického slova “descending”. Tuto variantu nepreferujeme, protože zmamená více psaní:
countries %>%arrange(desc(life_exp)) %>%select(country, life_exp)
# A tibble: 38 × 2
country life_exp
<chr> <dbl>
1 Switzerland 83.3
2 Spain 83.1
3 France 82.9
4 Italy 82.8
5 Norway 82.5
6 Luxembourg 82.4
7 Sweden 82.4
8 Iceland 82.4
9 Austria 81.9
10 Netherlands 81.6
# ℹ 28 more rows