Súčastou práce každého data analytika (štatistika) je aj príprava dát na analýzu alebo úprava do požadovaného tvaru. V praxi sa len zriedkavo stáva, že štatistik obdrží dáta pripravené na analýzu. Používatelia prostredia R si môžu prácu s dátami výrazne uľahčiť pomocou knižnice dplyr.

library(dplyr) # inštalácia cez install.packages("dplyr")

V nasledujúcom texte predstavím “len” základné funkcie knižnice, ich osvojením dokážete upravovať dáta v jednoduchých krokoch do požadovanej formy prehľadnejšie a rýchlejšie ako za použitia base R príkazov. Funkcie sú pomenované rozumne podľa toho čo robia:

Práca s dátami vyžaduje aj použitie viacerých funkcií v naviazanosti za sebou. Používať funkcie naväzujúce v slede za sebou sa dá viacerými spôsobmi. Zameráme sa na tzv “pipeline” v značení %>%, ktorá sa dá voľne interpretovať ako prepájaj funkcie z ľava do prava. Na poradí použitia funkcií záleží. Spôsob čítania %>% kódu bude rozpísané v riadkoch kódu za #.


Dáta mpg

Na trénovanie a ukážku využijeme dáta mpg z knižnice ggplot2. Ktoré obsahujú údaje o autách a ich výrobcovi (manufacturer), modeli (model), objem motora (displ), rok výroby (year), počet valcov (cyt), prevodovka (trans), náhon (drv), dojazd v meste a na diaľnici (cty a hwy), palivo (fl) a trieda (class).

library(ggplot2) # inštalácia cez install.packages("ggplot2")
data(mpg) # zavoláme dáta
mpg # vypíšeme
## # A tibble: 234 x 11
##    manufacturer model    displ  year   cyl trans   drv     cty   hwy fl   
##    <chr>        <chr>    <dbl> <int> <int> <chr>   <chr> <int> <int> <chr>
##  1 audi         a4        1.80  1999     4 auto(l… f        18    29 p    
##  2 audi         a4        1.80  1999     4 manual… f        21    29 p    
##  3 audi         a4        2.00  2008     4 manual… f        20    31 p    
##  4 audi         a4        2.00  2008     4 auto(a… f        21    30 p    
##  5 audi         a4        2.80  1999     6 auto(l… f        16    26 p    
##  6 audi         a4        2.80  1999     6 manual… f        18    26 p    
##  7 audi         a4        3.10  2008     6 auto(a… f        18    27 p    
##  8 audi         a4 quat…  1.80  1999     4 manual… 4        18    26 p    
##  9 audi         a4 quat…  1.80  1999     4 auto(l… 4        16    25 p    
## 10 audi         a4 quat…  2.00  2008     4 manual… 4        20    28 p    
## # ... with 224 more rows, and 1 more variable: class <chr>

V nasledujúcich častiach budeme pracovať s formátom tibble. Pre užívateľa sa tento formát skoro v ničom nelíši od base R data.frame. Výhoda nového formátu je skrytá vo vnútri, viacej detailov nájdete tu. Pre užívateľa je výhoda v zobrazení, po vypísaní ľahko môžete prečítať počet stĺpcov a riadkov, formát každého stĺpca a vidieť prvých 10 riadkov.


Vyber riadky filter( )

Asi najčastejšie potrebujeme len filtrovať, funkcia dovoľuje filtrovať aj za početných podmienok. Narpíklad. Chceme vybrať autá, ktoré boli vyrobené v roku 2008 a majú dojazd na diaľnici na galón paliva viacej ako 27 míľ.

filter(mpg, year == 2008, hwy > 27) # prvý argument sú dáta, potom môžete vkladať podmienky na filtrovanie.
## # A tibble: 33 x 11
##    manufacturer model    displ  year   cyl trans   drv     cty   hwy fl   
##    <chr>        <chr>    <dbl> <int> <int> <chr>   <chr> <int> <int> <chr>
##  1 audi         a4        2.00  2008     4 manual… f        20    31 p    
##  2 audi         a4        2.00  2008     4 auto(a… f        21    30 p    
##  3 audi         a4 quat…  2.00  2008     4 manual… 4        20    28 p    
##  4 chevrolet    malibu    2.40  2008     4 auto(l… f        22    30 r    
##  5 chevrolet    malibu    3.50  2008     6 auto(l… f        18    29 r    
##  6 honda        civic     1.80  2008     4 manual… f        26    34 r    
##  7 honda        civic     1.80  2008     4 auto(l… f        25    36 r    
##  8 honda        civic     1.80  2008     4 auto(l… f        24    36 c    
##  9 honda        civic     2.00  2008     4 manual… f        21    29 p    
## 10 hyundai      sonata    2.40  2008     4 auto(l… f        21    30 r    
## # ... with 23 more rows, and 1 more variable: class <chr>

Ten istý kód môžeme urobiť cez base R príkaz.

filter[filter$year == 2008 & filter$hwy > 27, ] # prehladnejšie? 

Alebo použime pipeline (%>%).

mpg %>% # zober dáta mpg a potom
  filter(year == 2008, hwy > 27) # filtruj rok rovný 2008 s dojazdom viacej ako 27 míl na diaľnici

Pri použití pipeline, funkcie za dátami už nemôžu obsahovať dáta v argumente (výhoda: šetrí to čas) tie sú zavolané na začiatku.


Zoraď riadky arrange( )

Rovnako aj funkcia na rozoradenie dovoľuje zoraďovať tiež početných podmienok. Zoraďme autá podľa vzdvižného objemu motora a potom podľa dojazdu na diaľnici.

arrange(mpg, displ, hwy) # zoraď dáta podľa vzdvižného objemu motora a tie podľa dojazdu
## # A tibble: 234 x 11
##    manufacturer model    displ  year   cyl trans   drv     cty   hwy fl   
##    <chr>        <chr>    <dbl> <int> <int> <chr>   <chr> <int> <int> <chr>
##  1 honda        civic     1.60  1999     4 manual… f        23    29 p    
##  2 honda        civic     1.60  1999     4 auto(l… f        24    32 r    
##  3 honda        civic     1.60  1999     4 manual… f        25    32 r    
##  4 honda        civic     1.60  1999     4 auto(l… f        24    32 r    
##  5 honda        civic     1.60  1999     4 manual… f        28    33 r    
##  6 audi         a4 quat…  1.80  1999     4 auto(l… 4        16    25 p    
##  7 audi         a4 quat…  1.80  1999     4 manual… 4        18    26 p    
##  8 audi         a4        1.80  1999     4 auto(l… f        18    29 p    
##  9 audi         a4        1.80  1999     4 manual… f        21    29 p    
## 10 volkswagen   passat    1.80  1999     4 manual… f        21    29 p    
## # ... with 224 more rows, and 1 more variable: class <chr>

Tento syntax zachovávajú všetky funkcie zahrnuté v knižnici. Začnime využívať výhody pipeline zapisovania a vyfiltrujme si autá, ktoré boli vyrobené v roku 2008 a majú dojazd v meste viacej ako 30 míľ zoraďme ich podľa zdvižného objemu motora.

mpg %>% # zober dáta mpg a potom
  filter(year == 2008, cty > 20) %>% # filtruj rok 2008 s dojazdom v meste viacej ako 20 míl v meste a potom
  arrange(displ) # zoraď podľa zdvižného objemu motora.
## # A tibble: 23 x 11
##    manufacturer model   displ  year   cyl trans    drv     cty   hwy fl   
##    <chr>        <chr>   <dbl> <int> <int> <chr>    <chr> <int> <int> <chr>
##  1 honda        civic    1.80  2008     4 manual(… f        26    34 r    
##  2 honda        civic    1.80  2008     4 auto(l5) f        25    36 r    
##  3 honda        civic    1.80  2008     4 auto(l5) f        24    36 c    
##  4 toyota       corolla  1.80  2008     4 manual(… f        28    37 r    
##  5 toyota       corolla  1.80  2008     4 auto(l4) f        26    35 r    
##  6 audi         a4       2.00  2008     4 auto(av) f        21    30 p    
##  7 honda        civic    2.00  2008     4 manual(… f        21    29 p    
##  8 volkswagen   gti      2.00  2008     4 manual(… f        21    29 p    
##  9 volkswagen   gti      2.00  2008     4 auto(s6) f        22    29 p    
## 10 volkswagen   jetta    2.00  2008     4 auto(s6) f        22    29 p    
## # ... with 13 more rows, and 1 more variable: class <chr>

Vyber stĺpce select( )

Tak ako sa pracuje s riadkami, tak sa rovnako pracuje aj so stĺpcami. Výber umožňuje aj v závislosti na poradí pôvodných dát. Funkcia zároveň aj zoraďuje stĺpce podľa toho v akom poradí ich napíšete.

select(mpg, manufacturer, drv:hwy, year) # vyber z dát výrobcu, všetky stĺpce medzí typom prevodovky a dojazdom na dialnici, nakoniec pridaj rok
## # A tibble: 234 x 5
##    manufacturer drv     cty   hwy  year
##    <chr>        <chr> <int> <int> <int>
##  1 audi         f        18    29  1999
##  2 audi         f        21    29  1999
##  3 audi         f        20    31  2008
##  4 audi         f        21    30  2008
##  5 audi         f        16    26  1999
##  6 audi         f        18    26  1999
##  7 audi         f        18    27  2008
##  8 audi         4        18    26  1999
##  9 audi         4        16    25  1999
## 10 audi         4        20    28  2008
## # ... with 224 more rows

Alebo funkcia sa dá použiť aj naopak, na “odobranie” stĺpca. Vezmime pipeline použitú vyššie a odoberme z neho na konci stĺpec s rokmi.

mpg %>% # zober dáta mpg a potom
  filter(year == 2008, cty > 20) %>% # filtruj rok 2008 s dojazdom v meste viacej ako 20 míl a potom
  arrange(displ) %>% # zoraď podľa zdvižného objemu motora a potom
  select(-year) # odober stĺpec rok
## # A tibble: 23 x 10
##    manufacturer model   displ   cyl trans   drv     cty   hwy fl    class 
##    <chr>        <chr>   <dbl> <int> <chr>   <chr> <int> <int> <chr> <chr> 
##  1 honda        civic    1.80     4 manual… f        26    34 r     subco…
##  2 honda        civic    1.80     4 auto(l… f        25    36 r     subco…
##  3 honda        civic    1.80     4 auto(l… f        24    36 c     subco…
##  4 toyota       corolla  1.80     4 manual… f        28    37 r     compa…
##  5 toyota       corolla  1.80     4 auto(l… f        26    35 r     compa…
##  6 audi         a4       2.00     4 auto(a… f        21    30 p     compa…
##  7 honda        civic    2.00     4 manual… f        21    29 p     subco…
##  8 volkswagen   gti      2.00     4 manual… f        21    29 p     compa…
##  9 volkswagen   gti      2.00     4 auto(s… f        22    29 p     compa…
## 10 volkswagen   jetta    2.00     4 auto(s… f        22    29 p     compa…
## # ... with 13 more rows

Pozor: Keby použijeme select na odobranie stĺpca rok, pred filtrovaním podľa roku, tak celá pipeline zlyhá. Takto môžeme jednoducho na seba vrstviť kroky logicky idúce po sebe.


Vytvor nový stĺpec mutate( )

Prvé dva stĺpce dát označujú výrobcu a model, použime funkciu na vytvorenie nového stĺpca obsahujúceho tieto informácie. Vytvorme ešte jeden nový stĺpec kde spočítame priemerný dojazd na jeden galón paliva z dojazdu v meste a na diaľnici. Nakoniec tabuľku zoradme podľa dojazdu.

mpg %>% # zober dáta mpg a potom
  mutate(auto = paste(manufacturer, "-", model), dojazd = (cty + hwy)/2) %>% # vytvor nový stĺpec auto z názvu výrobcu a modelu, vytvor novy stĺpec dojazd ako priemer dojazdov a potom
  select(auto, year, dojazd) %>% # nechaj stĺpce auto, year, dojazd a potom
  arrange(desc(dojazd)) # zorať podľa dojazdu zostupne 
## # A tibble: 234 x 3
##    auto                     year dojazd
##    <chr>                   <int>  <dbl>
##  1 volkswagen - new beetle  1999   39.5
##  2 volkswagen - jetta       1999   38.5
##  3 volkswagen - new beetle  1999   35.0
##  4 toyota - corolla         2008   32.5
##  5 honda - civic            1999   30.5
##  6 honda - civic            2008   30.5
##  7 toyota - corolla         1999   30.5
##  8 toyota - corolla         2008   30.5
##  9 honda - civic            2008   30.0
## 10 honda - civic            2008   30.0
## # ... with 224 more rows

Funkciou desc() viete zmeniť zoradenie na zostupne. Podľa dát najdlhší priemerný dojazd na galón paliva má “volkswagen - new beetle” z rokou 1999.


Spočítaj v stĺpci sumarize( )

Okrem počítania so stĺpcami potrebujeme počítať aj v riadkoch. Poďme hlbšie, zaujíma nás, aký je priemerný a maximálný dojazd v meste a na diaľnci, áut vyrobených v roku 1999.

mpg %>% # zober dáta mpg a potom
  filter(year == 1999) %>% # filtruj rok 1999 a potom
  summarize(mean(cty), max(cty), mean(hwy), max(hwy)) # spočítaj priemerný a maximálny dojazd v meste a na dialnici. 
## # A tibble: 1 x 4
##   `mean(cty)` `max(cty)` `mean(hwy)` `max(hwy)`
##         <dbl>      <dbl>       <dbl>      <dbl>
## 1        17.0        35.        23.4        44.

Takto sme si rýchlo vyfiltrovali a spočítali čo nás zaujíma v dvoj krokovom slede funkcií.


Rozdel riadky do skupín group_by( )

Niekto vám povie aby ste spočítali priemerné hodnoty dojazdov, ale pre každý jeden typ motoru vzhľadom na počet valcov. Tak začnime napríklad:

for(ii in unique(mpg$cyl)){
  mpg %>% # zober dáta mpg a potom
    filter(year == 2008, cyl = ii) %>% # filtruj rok 2008 a počet valcov ii a potom
    summarize(mean(cty), mean(hwy)) # spočítaj priemerný dojazd v meste a na dialnici. 
}

Použitie cyklu nie je veľmi pohodlné a často kradne váš čas keď sa ku kódu vraciate s odstupom času. Navyše, čo by ste robili keby sa úloha zmení a potrebujete ešte spočítať v rámci počtu valcov aj hodnoty pre každý typ paliva zvlášť?

V pipeline stačí pridať jeden riadok a celá robota ide rýchlejšie, pričom výstup máte v jednej tabulke. Aby sme to mali prehladnejšie pomenujme si tieto nové stĺpce.

mpg %>% # zober dáta mpg a potom
  filter(year == 2008) %>% # filtruj rok 2008 a potom
  group_by(cyl, fl) %>% # rozdel do skupín podľa počtu valcov a druhu paliva a potom
  summarize(priemer_mesto = mean(cty), priemer_dialnica = mean(hwy)) # spočítaj priemerný dojazd v meste a na dialnici. 
## # A tibble: 11 x 4
## # Groups:   cyl [?]
##      cyl fl    priemer_mesto priemer_dialnica
##    <int> <chr>         <dbl>            <dbl>
##  1     4 c             24.0              36.0
##  2     4 p             20.2              27.7
##  3     4 r             21.8              30.2
##  4     5 r             20.5              28.8
##  5     6 d             17.0              22.0
##  6     6 e             11.0              17.0
##  7     6 p             17.2              25.1
##  8     6 r             16.3              23.2
##  9     8 e              9.57             12.7
## 10     8 p             14.4              21.9
## 11     8 r             13.1              18.2

Pritvrďme, chceme vedieť ešte aj koľko áut obsahuje každá skupina a zoraďme si ich od najväčšej skupiny.

mpg %>% # zober dáta mpg a potom
  filter(year == 2008) %>% # filtruj rok 2008 a potom
  group_by(cyl, fl) %>% # rozdel do skupín podľa počtu valcov a druhu paliva a potom
  summarize(počet_v_skupine = n(), priemer_mesto = mean(cty), priemer_dialnica = mean(hwy)) %>% # spočítaj koľko áut je každej skupine, priemerný dojazd v meste a na dialnici a potom
  arrange(desc(počet_v_skupine)) # zorať podľa početnosti skupín zostupne.
## # A tibble: 11 x 5
## # Groups:   cyl [4]
##      cyl fl    počet_v_skupine priemer_mesto priemer_dialnica
##    <int> <chr>           <int>         <dbl>            <dbl>
##  1     8 r                  28         13.1              18.2
##  2     6 r                  23         16.3              23.2
##  3     4 r                  20         21.8              30.2
##  4     4 p                  15         20.2              27.7
##  5     6 p                   9         17.2              25.1
##  6     8 p                   8         14.4              21.9
##  7     8 e                   7          9.57             12.7
##  8     5 r                   4         20.5              28.8
##  9     4 c                   1         24.0              36.0
## 10     6 d                   1         17.0              22.0
## 11     6 e                   1         11.0              17.0

Najpočetnejšia skupina áut v dátach sú osem-válce s typom paliva “r”, táto najpočetnejšia skupina má zároveň aj najmenší priemerný dojazd.

To bola posledná základná funkcia, ktorú by mal ovládať každý kto chce pracovať s dátami v prostredí R rýchlo a efektívne. Ostatné funkie dopĺňajú vlastnosti už predstavených a ich osvojenie chce len čas a cvik.


Úloha

Pokúste sa pomocou pipeline spracovať dáta, tak aby ste zistili za každého výrobcu medián objemu motora pre autá s náhonom typu “f”. Výslednú tabuľku zoraďte podľa mediánu a v pipeline použite funkciu rename() na pomenovanie stĺpca “Výrobca”. Výlsedok by mal vyzerať takto:

## # A tibble: 9 x 2
##   Výrobca    Medián
##   <chr>       <dbl>
## 1 honda        1.60
## 2 audi         2.00
## 3 volkswagen   2.00
## 4 hyundai      2.40
## 5 toyota       2.40
## 6 nissan       3.00
## 7 chevrolet    3.10
## 8 dodge        3.30
## 9 pontiac      3.80

Ak sa vám to podarilo, tak ste pripravený na vyšší level práce s dplyr.


Ďalšie funkcie

Medzi základné funkcie ešte patria napríklad funkcia na náhodný výber riadkov, alebo generátor náhodnej podmnožiny:

Knižnica disponuje pár desiatkami užitočných funkcií, ako sú funkcie na agregovanie dátových tabuliek, prezhromaždovanie a podobne.

Využívaním pipeline písania sa približujete k v praxi používanej štruktúre SQL, zároveň jej príkazy sú veľmi podobné funkciám knižnice dplyr.