12  Široký a dlouhý formát

Důležitými pojmy v analýze jsou široký (wide) a dlouhý (long) formát uchovávání dat. Naštěstí pro nás se nejedná o nic složitého, jde pouze o způsob orientace dataframů. V širokém formátu jsou uchovány horizontálně, zatímco v dlouhém formátu jsou data orientovány vertikálně. Obsah dataframu se nemění, jediným rozdílem je forma:

Široký formát
country gdp life_exp poverty_risk
Czechia 207772.4 79.2 0.122
Germany 3386000.0 81.0 0.190
Norway 368388.9 82.5 0.160
Dlouhý formát
country name value
Czechia gdp 207772.400
Czechia life_exp 79.200
Czechia poverty_risk 0.122
Germany gdp 3386000.000
Germany life_exp 81.000
Germany poverty_risk 0.190
Norway gdp 368388.900
Norway life_exp 82.500
Norway poverty_risk 0.160

Široký vs Dlouhý formát

Zpravidla je široký formát intuitivnější pro lidi, zatímco ten dlouhý se lépe čte počítačům. V praxi proto budeme převádět data mezi formáty často a poslouží nám k tomu dvojice funkcí z balíčku tidyr: pivot_wider() a pivot_longer().

12.1 Z širokého do dlouhého formátu

Vraťme se k datasetu countries. V rámci analýzy nás může zajímat, jaká je nejvyšší pozorovaná hodnota každé z numerických proměnné. Jako bonus bychom také rádi věděli, které zemi tato hodnota patří.

Možností, jak se dostat ke kýženému výsledku, je více. Jedna z těch elegantnějších zahrnuje převedení dataframu do dlouhého formátu. Začneme tím, že z dataframu vybereme proměnnou country a všechny numerické proměnné, k čemuž poslouží funkce select(). Poté bude následovat funkce pivot_longer(). Tato funkce má jeden povinný argument, a to cols, pomocí kterého specifikujeme, které proměnné chceme převést do širokého formátu. Není nutné vybrat všechny existující proměnné, naopak pro naše potřeby je lepší nechat proměnnou countries v původní podobě. Kromě cols, jsou dalšími dvěma užitečnými argumenty names_to a values_to, pomocí kterých lze specifikovat názvy nově vytvořených sloupců. První z argumentů určí název sloupce obsahují názvy původních proměnných, druhý poté název sloupce, ve kterém budou uchovány naměřené hodnoty.

countries %>% 
  select(country, where(is.numeric)) %>% 
  pivot_longer(cols = -country,
               names_to = "variable",
               values_to = "max_value")
# A tibble: 342 × 3
   country  variable        max_value
   <chr>    <chr>               <dbl>
 1 Belgium  gdp            450506.   
 2 Belgium  population   11398589    
 3 Belgium  area            30528    
 4 Belgium  life_exp           81.2  
 5 Belgium  uni_prc             0.36 
 6 Belgium  poverty_risk        0.203
 7 Belgium  material_dep        0.113
 8 Belgium  hdi                 0.92 
 9 Belgium  dem_index           7.78 
10 Bulgaria gdp             55182.   
# … with 332 more rows

Tento kód provede výše popsané. Pomocí kombinace funkcí select() a pomocné funkce where() (viz. Sekce 10.2) vybereme proměnné. Funkce pivot_longer() se postará o zbytek. Argumentem cols určime, že převedeny do dlouhého formátu mají být všechny proměnné kromě country a nově vytvořené proměnné se mají jmenovat variable a max_value. Výsledkem je dataframe s menším počtem sloupců, zato výrazně větším počtem řádků. Každý řádek reprezentuje hodnotu jedné proměnné v jedné zemi.

Teď už zbývá jen vybrat pro každou z původních proměnných nejvyšší naměřenou hodnotu. Toho docílíme pomocí nám již známých funkcí group_by() a slice_max(). A to je vše! Z výsledného dataframu lze vyčíst že nejvyššímu pozorovanému Indexu lidského rozvoje (gdp) se těší Norsko, nebo že nejvyšší podíl lidí ohrožených chudobou je 41,6 % a trpí jím Severní Makedonie.

countries %>% 
  select(country, where(is.numeric)) %>% 
  pivot_longer(cols = -country,
               names_to = "variable",
               values_to = "max_value") %>% 
  group_by(variable) %>% 
  slice_max(max_value)
# A tibble: 9 × 3
# Groups:   variable [9]
  country         variable        max_value
  <chr>           <chr>               <dbl>
1 Turkey          area           783562    
2 Norway          dem_index           9.87 
3 Germany         gdp           3386000    
4 Norway          hdi                 0.95 
5 Switzerland     life_exp           83.3  
6 North Macedonia material_dep        0.481
7 Germany         population   82792351    
8 North Macedonia poverty_risk        0.416
9 Ireland         uni_prc             0.405

12.2 Z dlouhého do širokého formátu

Jak již asi tušíte, opakem pivot_longer() je funkce pivot_wider(), pomocí které je možné řádky “roztáhnout” do sloupců. Tato funkce má dva povinné argumenty, a to names_from a values_from. První z těchto argumentů převede hodnoty ve vybraném sloupci na názvy nových sloupců. Druhý argument poté nové sloupce zaplní hodnotami ze zvolené proměnné.

Poněkud umělým, ale názorným příkladem může být, pokud by naším cílem bylo vytvořit dataframe obsahující minimální hodnotu ohrožení chudobou podle převažujícího náboženského vyznání. Tento dataframů by měl být dobře srozumitelný pro naše čtenáře, a měl by proto mít podobu kontingenční tabulky.

Začneme podobně, jako v předchozím cvičení. Nejdříve vybereme všechny relevantní proměnné, tedy převažující náboženské vyznání (maj_belief), členství v Evropské unii (eu_member) a HDP (gdp). Poté kombinací funkcí group_by() a slice_min() získáme nejnižší pozorované hodnoty ohrožení chudobou pro každou kombinaci převažujícího vyznání a členství v EU. Nakonec už zbývá pouze využít funkce pivot_wider() pro převedení proměnné maj_belief() do sloupců a zaplnění nově vzniklých sloupců pomocí hodnot z poverty_risk. A máme hotovo

countries %>% 
  select(maj_belief, eu_member, poverty_risk) %>% 
  group_by(maj_belief, eu_member) %>%
  slice_min(poverty_risk) %>% 
  pivot_wider(names_from = maj_belief, values_from = poverty_risk)
# A tibble: 2 × 6
# Groups:   eu_member [2]
  eu_member catholic  islam nonbelief orthodox protestantism
  <chr>        <dbl>  <dbl>     <dbl>    <dbl>         <dbl>
1 no           0.181  0.413    NA        0.367         0.16 
2 yes          0.163 NA         0.122    0.252         0.157

Všimněme si, že některé buňky jsou prázdné, protože naše data neobsahují všechny kombinace náboženského vyznání a členství v Evropské unii.