class: center, middle, titular background-size: contain <img src="img/see.png" width="250px"/> # Sección 5: Manipulación de Datos con R - Extra ## **PROGRAMA INTERNACIONAL DE ESTADÍSTICA APLICADA A LA INVESTIGACIÓN CIENTÍFICA** #### MÓDULO: SOFTWARES PARA EL MANEJO DE DATOS <br> <br> Linda Cabrera Orellana #### Marzo, 2023 --- class: middle, center, inverse
# Datos Relacionales con `dplyr` --- #
Datos relacionales con `dplyr` .pull-left[La mayor parte del tiempo, nos vienen muchas tablas de información que debemos combinar para responder a nuestras preguntas de interés, a esto se le llama **datos relacionales**. Para trabajar con datos relacionales necesitas verbos que funcionen con pares de tablas y para esto existen tres familias de verbos diseñadas para trabajar con datos relacionales que son las 1) **uniones de transformación** (_mutating joins_), 2) **uniones de filtro** (_filtering joins_) y 3) **operaciones de conjuntos** (_set operations_). El lugar más común para encontrar datos relacionales es en un **sistema relacional de administración de bases de datos** (_Relational Data Base Management System_ en inglés), un concepto que abarca casi todas las bases de datos modernas. ] .pull-right[Una de las formas de mostrar las relaciones entre las diferentes tablas es mediante un diagrama: <img src="img/diagrama.png" width="100%" style="display: block; margin: auto;" /> ] --- #
Mutating joins Las **uniones de transformación** (del inglés _mutating joins_) agregan nuevas variables o columnas a un data frame a partir de las observaciones coincidentes en otra tabla. En las uniones de transformación tenemos algunos tipos de uniones: <div class="figure" style="text-align: center"> <img src="img/mutating.png" alt="Figura. Tipos de mutating joins" width="100%" /> <p class="caption">Figura. Tipos de mutating joins</p> </div> --- #
Mutating joins Para entender el `inner_join`, `left_join()`, `right_join()` y `full_join()`, vamos a crear los siguientes data frames con los que realizaremos las transformaciones: .pull-left[ ```r df_1 <- data.frame(Nombre= c('Belén', 'Noé', 'Salvador', 'Anne', 'Pablo', 'Rafaela', 'Victoria'), Edad = c(22,18,21,26,25,23,21), Ciudad= factor(c('Gye', 'Uio', 'Cue', 'Gye', 'Cue', 'Uio', 'Cue')) ) df_1 ## Nombre Edad Ciudad ## 1 Belén 22 Gye ## 2 Noé 18 Uio ## 3 Salvador 21 Cue ## 4 Anne 26 Gye ## 5 Pablo 25 Cue ## 6 Rafaela 23 Uio ## 7 Victoria 21 Cue ``` ] .pull-right[ ```r df_2 <- data.frame( A= c('Ana', 'Belén','Jose', 'Anne', 'Luis'), B= c(100,200,300,200,250), C= c('Soltera','Soltera','Casado','Divorciada','Soltero')) df_2 ## A B C ## 1 Ana 100 Soltera ## 2 Belén 200 Soltera ## 3 Jose 300 Casado ## 4 Anne 200 Divorciada ## 5 Luis 250 Soltero ``` ] --- #
Mutating joins .pull-left[ ### `inner_join()` Muestra las observaciones cuyas claves coinciden en ambos conjuntos de datos, en el argumento `by` se indican las variables que deben coincidir en ambos data.frames: ```r df_1 %>% inner_join(df_2, by = c("Nombre"="A")) ## Nombre Edad Ciudad B C ## 1 Belén 22 Gye 200 Soltera ## 2 Anne 26 Gye 200 Divorciada ``` En este caso, coinciden Belén y Anne, por lo que se forma un nuevo data.frame con las columnas de ambos data.frames y las 2 observaciones que coinciden. ] .pull-right[ ### `left_join()` Muestra todas las observaciones del conjunto de la **izquierda** `df1` pero añade las columnas y los datos del conjunto de la derecha `df2`, coincidan o no coincidan. Si no coinciden los datos, se agregan con `NA`. ```r df_1 %>% left_join(df_2, by = c("Nombre"="A")) ## Nombre Edad Ciudad B C ## 1 Belén 22 Gye 200 Soltera ## 2 Noé 18 Uio NA <NA> ## 3 Salvador 21 Cue NA <NA> ## 4 Anne 26 Gye 200 Divorciada ## 5 Pablo 25 Cue NA <NA> ## 6 Rafaela 23 Uio NA <NA> ## 7 Victoria 21 Cue NA <NA> ``` ] --- #
Mutating joins .pull-left[ ### `right_join()` Muestra todas las observaciones del conjunto de la **derecha** `df2` pero añade las columnas y los datos del conjunto de la izquierda `df1`, coincidan o no coincidan. Si no coinciden los datos, se agregan con `NA`. ```r df_1 %>% right_join(df_2, by = c("Nombre"="A")) ## Nombre Edad Ciudad B C ## 1 Belén 22 Gye 200 Soltera ## 2 Anne 26 Gye 200 Divorciada ## 3 Ana NA <NA> 100 Soltera ## 4 Jose NA <NA> 300 Casado ## 5 Luis NA <NA> 250 Soltero ``` ] .pull-right[ ### `full_join()` Muestra las observaciones (filas) de ambos conjuntos de datos, cuando los datos no coinciden, se agregan con `NA`. ```r df_1 %>% full_join(df_2, by = c("Nombre"="A")) ## Nombre Edad Ciudad B C ## 1 Belén 22 Gye 200 Soltera ## 2 Noé 18 Uio NA <NA> ## 3 Salvador 21 Cue NA <NA> ## 4 Anne 26 Gye 200 Divorciada ## 5 Pablo 25 Cue NA <NA> ## 6 Rafaela 23 Uio NA <NA> ## 7 Victoria 21 Cue NA <NA> ## 8 Ana NA <NA> 100 Soltera ## 9 Jose NA <NA> 300 Casado ## 10 Luis NA <NA> 250 Soltero ``` ] --- #
Filtering joins Las **uniones de filtro** (del inglés _filtering joins_) filtran observaciones en un data frame con base en si coinciden o no con una observación de otra tabla. .pull-left[ ### `semi_join()` Muestra las observaciones del conjunto de la izquierda que tiene coincidencias con el conjunto de la derecha, en este caso no se agregan nuevas columnas, se mantienen las columnas del conjunto de la izquierda: ```r df_1 %>% semi_join(df_2, by = c("Nombre"="A")) ## Nombre Edad Ciudad ## 1 Belén 22 Gye ## 2 Anne 26 Gye ``` ] .pull-right[ ### `anti_join()` Muestra las observaciones del conjunto de la izquierda que no tiene coincidencias con el conjunto de la derecha, en este caso tampoco se agregan nuevas columnas, se mantienen las columnas del conjunto de la izquierda: ```r df_1 %>% anti_join(df_2, by = c("Nombre"="A")) ## Nombre Edad Ciudad ## 1 Noé 18 Uio ## 2 Salvador 21 Cue ## 3 Pablo 25 Cue ## 4 Rafaela 23 Uio ## 5 Victoria 21 Cue ``` ] --- #
Set operations Las **operaciones de conjuntos** (del inglés _set operations_) tratan las observaciones como elementos de un conjunto. Las comparaciones se realizan entre _conjuntos que contengan las mismas columnas_, pues se revisa cómo difieren las observaciones entre los conjuntos, para esto, revisaremos las funciones `intersect()`, `union()` y `setdiff()`. Para ejemplificar esta parte crearemos el data.frame `df3`. .pull-left[ ```r df_3 <- data.frame(Nombre= c('Belén', 'Noé', 'María', 'Anne', 'Pablo'), Edad = c(22,18,21,26,25), Ciudad= factor(c('Cue', 'Uio', 'Cue', 'Gye', 'Cue'))) df_3 ## Nombre Edad Ciudad ## 1 Belén 22 Cue ## 2 Noé 18 Uio ## 3 María 21 Cue ## 4 Anne 26 Gye ## 5 Pablo 25 Cue ``` ] .pull-right[ ### `intersect()` Devuelve las observaciones comunes entre ambos conjuntos. ```r intersect(df_1, df_3) ## Nombre Edad Ciudad ## 1 Noé 18 Uio ## 2 Anne 26 Gye ## 3 Pablo 25 Cue ``` ] --- #
Set operations .pull-left[ ### `union()` Devuelve las observaciones únicas en ambos conjuntos, es decir que no se repiten en ninguno de los dos conjuntos. ```r union(df_1, df_3) ## Nombre Edad Ciudad ## 1 Belén 22 Gye ## 2 Noé 18 Uio ## 3 Salvador 21 Cue ## 4 Anne 26 Gye ## 5 Pablo 25 Cue ## 6 Rafaela 23 Uio ## 7 Victoria 21 Cue ## 8 Belén 22 Cue ## 9 María 21 Cue ``` ] .pull-right[ ### `setdiff()` Devuelve las observaciones en el primer conjunto pero que son diferentes del segundo conjunto. ```r setdiff(df_1, df_3) ## Nombre Edad Ciudad ## 1 Belén 22 Gye ## 2 Salvador 21 Cue ## 3 Rafaela 23 Uio ## 4 Victoria 21 Cue ``` ] --- background-color: var(--azul-claro) class: middle, center, inverse
## PRÁCTICA --- #
Práctica: ¡5 minutos! 1. Crea el objeto `preguntas` cargando la pestaña `DATA2` del archivo `EXCELprofesores.xlsx`. Este archivo contiene el código del encuestado y las respuestas a 2 preguntas adicionales de la encuesta. 2. ¿Qué join necesitamos realizar en nuestros datos para unificar los data.frames `profesores` y `preguntas`? Efectúelo. --- class: middle, center, inverse <img src="img/tidyr.png" width="150px"> # Datos ordenados con `tidyr` --- #
Datos ordenados Existen tres reglas interrelacionadas que hacen que un conjunto de datos sea ordenado: * Cada variable debe tener su propia columna. * Cada observación debe tener su propia fila. * Cada valor debe tener su propia celda. <div class="figure" style="text-align: center"> <img src="img/tidy_data.png" alt="Figura: Reglas que hacen que un conjunto de datos sea ordenado" width="1000" /> <p class="caption">Figura: Reglas que hacen que un conjunto de datos sea ordenado</p> </div> --- #
Funciones del paquete `tidyr` <br> <br> <br> | Función | Acción | |:---------------|-------------------------------------------:| | `pivot_longer()` | *Modifica el nombre de las variables, arreglando los valores a lo largo del conjunto de datos* | | `pivot_wider()` | *Selecciona o descarta variables (columnas) de un conjunto de datos, arreglando los valores a lo ancho del conjunto de datos* | <br> <br> <br> <br> .footnote[ [tidyr.tidyverse.org](https://tidyr.tidyverse.org/) ] --- #
Ordenar datos a lo largo <br> .pull-left[ .center[ <img src="img/longer.png" width="600px"> ] La estructura de la función es la siguiente: ```r pivot_longer(data, cols, names_to = "name", values_to = "value", values_drop_na = FALSE) ``` ] .pull-right[ Se puede observar que en la primera tabla hay dos columnas que no corresponden a nombres de variables, puesto que el nombre de esas dos columnas deberían formar una sola columna denominada `year`. Aplicando `pivot_longer()` los nombres de las columnas forman una nueva variable llamada `year` y los valores que correspondían a esas columnas se organizan en otra nueva columna denominada `cases`. - **`pivot_longer()`** alarga datos al contraer varias columnas en dos. - Los nombres de columna se mueven a una nueva columna de `names_to` y, - Los valores a una nueva columna de `values_to`. ] --- #
Ordenar datos a lo largo La librería `datos` contiene algunos [conjuntos de datos](https://www.rdocumentation.org/packages/datos/versions/0.5.0) que pueden servir para practicar, en muchos cursos utilizan estos conjuntos de datos para enseñar R. En este caso utilizamos esta librería para cargar los datos que se encuentran en `table4a` que contiene registros de tuberculosis de la Organización Mundial de la Salud (variante 4a). .pull-left[ ```r ## cargamos el paquete library(datos) ## imprimimos la tabla4a tabla4a ## # A tibble: 3 × 3 ## pais `1999` `2000` ## <chr> <int> <int> ## 1 Afganistán 745 2666 ## 2 Brasil 37737 80488 ## 3 China 212258 213766 ``` ] .pull-right[ ```r ## aplicamos pivot_longer() para corregir los datos a lo largo tabla4a %>% pivot_longer(cols = c(`1999`, `2000`), names_to = "anio", values_to = "casos") ## # A tibble: 6 × 3 ## pais anio casos ## <chr> <chr> <int> ## 1 Afganistán 1999 745 ## 2 Afganistán 2000 2666 ## 3 Brasil 1999 37737 ## 4 Brasil 2000 80488 ## 5 China 1999 212258 ## 6 China 2000 213766 ``` ] --- #
Ordenar datos a lo ancho <br> .pull-left[ .center[ <img src="img/wider.png" width="600px"> ] ] .pull-right[ Se puede observar que en la primera tabla hay una columna que contiene `cases` y `pop`, estas observaciones deben ser columnas, además están duplicando las filas. Aplicando `pivot_wider()` la columna `type` se anula formando dos nuevas columnas llamadas `cases` y `pop`. **`pivot_wider()`** es lo contrario de `pivot_longer()`, amplia los datos expandiendo dos columnas en varias. Una columna proporciona los nuevos nombres de columna, la otra los valores. La estructura de `pivot_wider()` es la siguiente: ```r pivot_wider(data, names_from = "name", values_from = "value") ``` ] --- #
Ordenar datos a lo ancho Para este ejemplo, usamos el tabla `tabla2` de la librería `datos`: .pull-left[ ```r ## imprimimos la tabla2 tabla2 ## # A tibble: 12 × 4 ## pais anio tipo cuenta ## <chr> <int> <chr> <int> ## 1 Afganistán 1999 casos 745 ## 2 Afganistán 1999 población 19987071 ## 3 Afganistán 2000 casos 2666 ## 4 Afganistán 2000 población 20595360 ## 5 Brasil 1999 casos 37737 ## 6 Brasil 1999 población 172006362 ## 7 Brasil 2000 casos 80488 ## 8 Brasil 2000 población 174504898 ## 9 China 1999 casos 212258 ## 10 China 1999 población 1272915272 ## 11 China 2000 casos 213766 ## 12 China 2000 población 1280428583 ``` ] .pull-right[ ```r ## aplicamos pivot_wider() para corregir los datos a lo largo tabla2 %>% pivot_wider(names_from = tipo, values_from = cuenta) ## # A tibble: 6 × 4 ## pais anio casos población ## <chr> <int> <int> <int> ## 1 Afganistán 1999 745 19987071 ## 2 Afganistán 2000 2666 20595360 ## 3 Brasil 1999 37737 172006362 ## 4 Brasil 2000 80488 174504898 ## 5 China 1999 212258 1272915272 ## 6 China 2000 213766 1280428583 ``` ] --- class: middle, center, inverse <br> <br> # Manipulación de Datos con R - Extra ### Linda Cabrera Orellana .pull-left[ .center[ ### [@socecuest
](https://www.facebook.com/socecuest) ### [@see_estadistica
](https://www.instagram.com/see_estadistica/) ]] .pull-right[ .center[ ### [@see_estadistica
](https://twitter.com/see_estadistica) ### [@sosecuest
](https://t.me/sosecuest) ]]