Tema 6. Tydiverse-dplyr

Manuel Barrios - Instituto de Investigaciones de Zacapa

2022-03-06

Tydiverse es una colección de bibliotecas de R para Ciencia de Datos https://www.tidyverse.org/, entre las que se encuentra dplyr.

La instalación de la biblioteca dplyr se realiza con el siguiente comando:

install.packages("dplyr")

dplyr contiene funciones para el manejo de datos, puedes encontrar un cheat sheet en el siguiente enlace.

La biblioteca dplyr contiene las siguientes funciones:

Funcion Descripcion
mutate( ) Agrega nuevas variables que resultan de aplicar una función a las variables existentes.
select( ) Selecciona variables basadas en su nombre.
filter( ) Filtra datos con base en su valor.
summarise( ) Reduce un conjunto de valores a un solo valor (ej. media).
arrange( ) Realiza cambios de orden de las filas con base a un criterio establecido.

En la biblioteca dplyr estaremos utilizando operadores relacionales y booleanos.

Operadores relacionales

Operador Descripción
< Menor que
> Mayor que
<= Menor o igual
>= Mayor o igual
== Igual que
!= Difente a

Operadores Booleanos

Operador Lectura Descripción
x | y x O y Retorna un valor verdadero, si alguno de los argumentos es verdadero.
x & y x Y y Retorna un valor verdadero, solo si ambos son verdaderos
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
head(starwars, 5)
## # A tibble: 5 x 14
##   name     height  mass hair_color skin_color  eye_color birth_year sex   gender
##   <chr>     <int> <dbl> <chr>      <chr>       <chr>          <dbl> <chr> <chr> 
## 1 Luke Sk~    172    77 blond      fair        blue            19   male  mascu~
## 2 C-3PO       167    75 <NA>       gold        yellow         112   none  mascu~
## 3 R2-D2        96    32 <NA>       white, blue red             33   none  mascu~
## 4 Darth V~    202   136 none       white       yellow          41.9 male  mascu~
## 5 Leia Or~    150    49 brown      light       brown           19   fema~ femin~
## # ... with 5 more variables: homeworld <chr>, species <chr>, films <list>,
## #   vehicles <list>, starships <list>
names(starwars)
##  [1] "name"       "height"     "mass"       "hair_color" "skin_color"
##  [6] "eye_color"  "birth_year" "sex"        "gender"     "homeworld" 
## [11] "species"    "films"      "vehicles"   "starships"
dim(starwars)
## [1] 87 14

Función filter( )

Vamos a filtrar con base a un valor de una columna que contiene caracteres. Para conectar la base de datos con la función vamos a utilizar el operador pip %>%

starwars %>% filter(eye_color == "brown")
## # A tibble: 21 x 14
##    name     height  mass hair_color skin_color eye_color birth_year sex   gender
##    <chr>     <int> <dbl> <chr>      <chr>      <chr>          <dbl> <chr> <chr> 
##  1 Leia Or~    150  49   brown      light      brown           19   fema~ femin~
##  2 Biggs D~    183  84   black      light      brown           24   male  mascu~
##  3 Han Solo    180  80   brown      fair       brown           29   male  mascu~
##  4 Yoda         66  17   white      green      brown          896   male  mascu~
##  5 Boba Fe~    183  78.2 black      fair       brown           31.5 male  mascu~
##  6 Lando C~    177  79   black      dark       brown           31   male  mascu~
##  7 Arvel C~     NA  NA   brown      fair       brown           NA   male  mascu~
##  8 Wicket ~     88  20   brown      brown      brown            8   male  mascu~
##  9 Quarsh ~    183  NA   black      dark       brown           62   <NA>  <NA>  
## 10 Shmi Sk~    163  NA   black      fair       brown           72   fema~ femin~
## # ... with 11 more rows, and 5 more variables: homeworld <chr>, species <chr>,
## #   films <list>, vehicles <list>, starships <list>

Ahora vamos a filtrar con base a dos valores de una columna que contiene caracteres.

starwars %>% filter(eye_color == "brown" | eye_color =="blue")
## # A tibble: 40 x 14
##    name     height  mass hair_color skin_color eye_color birth_year sex   gender
##    <chr>     <int> <dbl> <chr>      <chr>      <chr>          <dbl> <chr> <chr> 
##  1 Luke Sk~    172    77 blond      fair       blue            19   male  mascu~
##  2 Leia Or~    150    49 brown      light      brown           19   fema~ femin~
##  3 Owen La~    178   120 brown, gr~ light      blue            52   male  mascu~
##  4 Beru Wh~    165    75 brown      light      blue            47   fema~ femin~
##  5 Biggs D~    183    84 black      light      brown           24   male  mascu~
##  6 Anakin ~    188    84 blond      fair       blue            41.9 male  mascu~
##  7 Wilhuff~    180    NA auburn, g~ fair       blue            64   male  mascu~
##  8 Chewbac~    228   112 brown      unknown    blue           200   male  mascu~
##  9 Han Solo    180    80 brown      fair       brown           29   male  mascu~
## 10 Jek Ton~    180   110 brown      fair       blue            NA   male  mascu~
## # ... with 30 more rows, and 5 more variables: homeworld <chr>, species <chr>,
## #   films <list>, vehicles <list>, starships <list>

También pueda ser que nos interesa aplicar un filtro a otra columna, por ejemplo que además de poseer ojos azules ó cafés midan igual o más a 150.

starwars %>% filter(eye_color == "brown" | eye_color =="blue" | height >= 150)
## # A tibble: 75 x 14
##    name    height  mass hair_color  skin_color eye_color birth_year sex   gender
##    <chr>    <int> <dbl> <chr>       <chr>      <chr>          <dbl> <chr> <chr> 
##  1 Luke S~    172    77 blond       fair       blue            19   male  mascu~
##  2 C-3PO      167    75 <NA>        gold       yellow         112   none  mascu~
##  3 Darth ~    202   136 none        white      yellow          41.9 male  mascu~
##  4 Leia O~    150    49 brown       light      brown           19   fema~ femin~
##  5 Owen L~    178   120 brown, grey light      blue            52   male  mascu~
##  6 Beru W~    165    75 brown       light      blue            47   fema~ femin~
##  7 Biggs ~    183    84 black       light      brown           24   male  mascu~
##  8 Obi-Wa~    182    77 auburn, wh~ fair       blue-gray       57   male  mascu~
##  9 Anakin~    188    84 blond       fair       blue            41.9 male  mascu~
## 10 Wilhuf~    180    NA auburn, gr~ fair       blue            64   male  mascu~
## # ... with 65 more rows, and 5 more variables: homeworld <chr>, species <chr>,
## #   films <list>, vehicles <list>, starships <list>

Ahora supongamos que queremos eliminar todas las filas que contengan NA’s

starwars %>% filter(eye_color == "brown" | eye_color =="blue" | height >= 150) %>% na.omit()
## # A tibble: 29 x 14
##    name    height  mass hair_color  skin_color eye_color birth_year sex   gender
##    <chr>    <int> <dbl> <chr>       <chr>      <chr>          <dbl> <chr> <chr> 
##  1 Luke S~    172    77 blond       fair       blue            19   male  mascu~
##  2 Darth ~    202   136 none        white      yellow          41.9 male  mascu~
##  3 Leia O~    150    49 brown       light      brown           19   fema~ femin~
##  4 Owen L~    178   120 brown, grey light      blue            52   male  mascu~
##  5 Beru W~    165    75 brown       light      blue            47   fema~ femin~
##  6 Biggs ~    183    84 black       light      brown           24   male  mascu~
##  7 Obi-Wa~    182    77 auburn, wh~ fair       blue-gray       57   male  mascu~
##  8 Anakin~    188    84 blond       fair       blue            41.9 male  mascu~
##  9 Chewba~    228   112 brown       unknown    blue           200   male  mascu~
## 10 Han So~    180    80 brown       fair       brown           29   male  mascu~
## # ... with 19 more rows, and 5 more variables: homeworld <chr>, species <chr>,
## #   films <list>, vehicles <list>, starships <list>
names(starwars)
##  [1] "name"       "height"     "mass"       "hair_color" "skin_color"
##  [6] "eye_color"  "birth_year" "sex"        "gender"     "homeworld" 
## [11] "species"    "films"      "vehicles"   "starships"

Supongamos que ahora queremos que nos ordene nuestra selección previa por estatura, por lo que necesitamos aplicar el comando arrange( )

starwars %>% filter(eye_color == "brown" | eye_color =="blue" | height >= 150) %>% na.omit() %>% arrange(height)
## # A tibble: 29 x 14
##    name     height  mass hair_color skin_color eye_color birth_year sex   gender
##    <chr>     <int> <dbl> <chr>      <chr>      <chr>          <dbl> <chr> <chr> 
##  1 Wicket ~     88  20   brown      brown      brown              8 male  mascu~
##  2 Leia Or~    150  49   brown      light      brown             19 fema~ femin~
##  3 Beru Wh~    165  75   brown      light      blue              47 fema~ femin~
##  4 Padmé A~    165  45   brown      light      brown             46 fema~ femin~
##  5 Barriss~    166  50   black      yellow     blue              40 fema~ femin~
##  6 Wedge A~    170  77   brown      fair       hazel             21 male  mascu~
##  7 Palpati~    170  75   grey       pale       yellow            82 male  mascu~
##  8 Luminar~    170  56.2 black      yellow     blue              58 fema~ femin~
##  9 Luke Sk~    172  77   blond      fair       blue              19 male  mascu~
## 10 Lobot       175  79   none       light      blue              37 male  mascu~
## # ... with 19 more rows, and 5 more variables: homeworld <chr>, species <chr>,
## #   films <list>, vehicles <list>, starships <list>

También podemos aplicar dos filtros consecutivos

na.omit(starwars %>% filter(eye_color == "brown" | eye_color =="blue" | height >= 150) %>% na.omit() %>% arrange(species,height))
## # A tibble: 29 x 14
##    name     height  mass hair_color skin_color eye_color birth_year sex   gender
##    <chr>     <int> <dbl> <chr>      <chr>      <chr>          <dbl> <chr> <chr> 
##  1 Ki-Adi-~    198    82 white      pale       yellow            92 male  mascu~
##  2 Wicket ~     88    20 brown      brown      brown              8 male  mascu~
##  3 Jar Jar~    196    66 none       orange     orange            52 male  mascu~
##  4 Leia Or~    150    49 brown      light      brown             19 fema~ femin~
##  5 Beru Wh~    165    75 brown      light      blue              47 fema~ femin~
##  6 Padmé A~    165    45 brown      light      brown             46 fema~ femin~
##  7 Wedge A~    170    77 brown      fair       hazel             21 male  mascu~
##  8 Palpati~    170    75 grey       pale       yellow            82 male  mascu~
##  9 Luke Sk~    172    77 blond      fair       blue              19 male  mascu~
## 10 Lobot       175    79 none       light      blue              37 male  mascu~
## # ... with 19 more rows, and 5 more variables: homeworld <chr>, species <chr>,
## #   films <list>, vehicles <list>, starships <list>

Tal como está desplegado cuesta ver el arreglo, hagamos una selección de las comlumnas que nos interesan y coloquemolas en el orden que nos convenga utilizando la función select( )

starwars %>% filter(eye_color == "brown" | eye_color =="blue" | height >= 150) %>% na.omit() %>% arrange(species,height) %>% select(name, species, hair_color,height)
## # A tibble: 29 x 4
##    name                  species hair_color height
##    <chr>                 <chr>   <chr>       <int>
##  1 Ki-Adi-Mundi          Cerean  white         198
##  2 Wicket Systri Warrick Ewok    brown          88
##  3 Jar Jar Binks         Gungan  none          196
##  4 Leia Organa           Human   brown         150
##  5 Beru Whitesun lars    Human   brown         165
##  6 Padmé Amidala         Human   brown         165
##  7 Wedge Antilles        Human   brown         170
##  8 Palpatine             Human   grey          170
##  9 Luke Skywalker        Human   blond         172
## 10 Lobot                 Human   none          175
## # ... with 19 more rows
starwars %>% filter(eye_color == "brown" | eye_color =="blue" | height >= 150) %>% na.omit() %>% arrange(species,height) %>% select(name, species, hair_color,height,mass)
## # A tibble: 29 x 5
##    name                  species hair_color height  mass
##    <chr>                 <chr>   <chr>       <int> <dbl>
##  1 Ki-Adi-Mundi          Cerean  white         198    82
##  2 Wicket Systri Warrick Ewok    brown          88    20
##  3 Jar Jar Binks         Gungan  none          196    66
##  4 Leia Organa           Human   brown         150    49
##  5 Beru Whitesun lars    Human   brown         165    75
##  6 Padmé Amidala         Human   brown         165    45
##  7 Wedge Antilles        Human   brown         170    77
##  8 Palpatine             Human   grey          170    75
##  9 Luke Skywalker        Human   blond         172    77
## 10 Lobot                 Human   none          175    79
## # ... with 19 more rows

Supongaos que ahora queremos obtener el Indice de Masa Corporal, de acuerdo con el CDC, el índice de masa corporal (IMC) es el peso de una persona en kilogramos dividido por el cuadrado de la estatura en metros.

starwars %>% select(name, species, hair_color,height,mass) %>% mutate(IMC= (mass)/((height/100)^2)) %>% na.omit()
## # A tibble: 53 x 6
##    name               species hair_color    height  mass   IMC
##    <chr>              <chr>   <chr>          <int> <dbl> <dbl>
##  1 Luke Skywalker     Human   blond            172    77  26.0
##  2 Darth Vader        Human   none             202   136  33.3
##  3 Leia Organa        Human   brown            150    49  21.8
##  4 Owen Lars          Human   brown, grey      178   120  37.9
##  5 Beru Whitesun lars Human   brown            165    75  27.5
##  6 Biggs Darklighter  Human   black            183    84  25.1
##  7 Obi-Wan Kenobi     Human   auburn, white    182    77  23.2
##  8 Anakin Skywalker   Human   blond            188    84  23.8
##  9 Chewbacca          Wookiee brown            228   112  21.5
## 10 Han Solo           Human   brown            180    80  24.7
## # ... with 43 more rows

Ahora supongamos que queremos saber que significa el IMC y luego arreglemos por orden de IMC

st1<-
  starwars %>% 
    select(name, species, height, mass) %>% 
    mutate(IMC= (mass)/((height/100)^2)) %>% 
    mutate(
      IMC2= case_when(
        IMC <18.5 ~ "Peso inferior al normal",
        IMC >=18.5 & IMC <=24.9 ~ "Normal", 
        IMC >24.9 & IMC <=29.9 ~ "Peso superior al normal",
        IMC >29.9 ~ "Obesidad",
        TRUE ~ "otro"
        )
      ) %>% 
  arrange(IMC)
st1
## # A tibble: 87 x 6
##    name          species    height  mass   IMC IMC2                   
##    <chr>         <chr>       <int> <dbl> <dbl> <chr>                  
##  1 Wat Tambor    Skakoan       193    48  12.9 Peso inferior al normal
##  2 Adi Gallia    Tholothian    184    50  14.8 Peso inferior al normal
##  3 Sly Moore     <NA>          178    48  15.1 Peso inferior al normal
##  4 Roos Tarpals  Gungan        224    82  16.3 Peso inferior al normal
##  5 Padmé Amidala Human         165    45  16.5 Peso inferior al normal
##  6 Lama Su       Kaminoan      229    88  16.8 Peso inferior al normal
##  7 Jar Jar Binks Gungan        196    66  17.2 Peso inferior al normal
##  8 Ayla Secura   Twi'lek       178    55  17.4 Peso inferior al normal
##  9 Shaak Ti      Togruta       178    57  18.0 Peso inferior al normal
## 10 Barriss Offee Mirialan      166    50  18.1 Peso inferior al normal
## # ... with 77 more rows

Con la función summarise( ) podemos realizar diversas operaciones, como calcular la media, la desviación estandar, realizar sumatoria, etc.

st1 %>% 
  na.omit() %>%
  summarise(Altura.prom = mean(height),
            Altura.sd = sd(height),
            Masa.prom = mean(mass),
            Masa.sd = sd(mass),
            IMC.prom = mean(IMC),
            IMC.sd=sd(IMC),
            )
## # A tibble: 1 x 6
##   Altura.prom Altura.sd Masa.prom Masa.sd IMC.prom IMC.sd
##         <dbl>     <dbl>     <dbl>   <dbl>    <dbl>  <dbl>
## 1        174.      35.8      98.2    171.     32.3   55.3

Que sucede si combinamos la operación anterior con group_by

st1 %>% 
  na.omit() %>%
  group_by(species) %>%
  summarise(Altura.prom = mean(height),
            Altura.sd = sd(height),
            Masa.prom = mean(mass),
            Masa.sd = sd(mass),
            IMC.prom = mean(IMC),
            IMC.sd=sd(IMC),
            )
## # A tibble: 31 x 7
##    species   Altura.prom Altura.sd Masa.prom Masa.sd IMC.prom IMC.sd
##    <chr>           <dbl>     <dbl>     <dbl>   <dbl>    <dbl>  <dbl>
##  1 Aleena            79       NA        15      NA       24.0 NA    
##  2 Besalisk         198       NA       102      NA       26.0 NA    
##  3 Cerean           198       NA        82      NA       20.9 NA    
##  4 Clawdite         168       NA        55      NA       19.5 NA    
##  5 Droid            140       52.0      69.8    51.0     32.7  3.87 
##  6 Dug              112       NA        40      NA       31.9 NA    
##  7 Ewok              88       NA        20      NA       25.8 NA    
##  8 Geonosian        183       NA        80      NA       23.9 NA    
##  9 Gungan           210       19.8      74      11.3     16.8  0.592
## 10 Human            180.      11.4      82.8    19.4     25.5  4.55 
## # ... with 21 more rows