Cargando paquetes

library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.1 ──
## ✓ ggplot2 3.3.3     ✓ purrr   0.3.4
## ✓ tibble  3.1.1     ✓ dplyr   1.0.6
## ✓ tidyr   1.1.3     ✓ stringr 1.4.0
## ✓ readr   1.4.0     ✓ forcats 0.5.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()

1. Pivotar

Para solucionar estos problemas necesitarás las dos funciones más importantes de tidyr:

pivot_longer() (pivotar a lo largo), y pivot_wider() (pivotar a lo ancho).

Datos largos:

Un problema común es cuando en un dataset los nombres de las columnas no representan nombres de variables, sino que representan los valores de una variable. Tomando el caso de la tabla4a: los nombres de las columnas 1999 y 2000 representan los valores de la variable year, los valores en las columnas 1999 y 2000 representan valores de la variable cases y cada fila representa dos observaciones en lugar de una.

Para ordenar un dataset como este necesitamos pivotar las columnas que no se ajustan, en un nuevo par de variables. Para describir dicha operación necesitamos tres parámetros:

El conjunto de columnas cuyos nombres son valores y no variables. En este ejemplo son las columnas 1999 y 2000. El nombre de la variable al que moveremos los nombres de las columnas. En este caso es year El nombre de la variable al que moveremos los valores de las columnas. En este caso cases

Con estos parámetros podemos utilizar la función pivot_longer() (pivotar a lo largo):

table4a %>% 
  pivot_longer(c(`1999`, `2000`), names_to = "year", values_to = "cases")
## # A tibble: 6 x 3
##   country     year   cases
##   <chr>       <chr>  <int>
## 1 Afghanistan 1999     745
## 2 Afghanistan 2000    2666
## 3 Brazil      1999   37737
## 4 Brazil      2000   80488
## 5 China       1999  212258
## 6 China       2000  213766

Las columnas a pivotar quedan seleccionadas siguiendo el estilo de notación de dplyr::select(). En este caso hay solo dos columnas, por lo que las listamos individualmente.

Ten en consideración que “1999” y “2000” son nombres no-sintáxicos (debido a que no comienzan con una letra) por lo que los rodeamos con acentos graves (o backticks).

Las variables “year” y “cases” no existen todavía en la tabla4a, por lo que tenemos que poner sus nombres entre comillas. En el resultado final, las columnas pivotadas se eliminan y obtenemos la nuevas columnas year y cases. La relación entre las variables originales se mantiene, tal como se puede observar en la imagen anterior.

Podemos usar pivot_longer() para ordenar tabla4b de modo similar. La única diferencia es la variable almacenada en los valores de las celdas.

table4b %>% 
  pivot_longer(c(`1999`, `2000`), names_to = "year", values_to = "population")
## # A tibble: 6 x 3
##   country     year  population
##   <chr>       <chr>      <int>
## 1 Afghanistan 1999    19987071
## 2 Afghanistan 2000    20595360
## 3 Brazil      1999   172006362
## 4 Brazil      2000   174504898
## 5 China       1999  1272915272
## 6 China       2000  1280428583

Para combinar las versiones ordenadas de tabla4a y tabla4b en un único tibble, necesitamos usar dplyr::left_join(), función necesaria para trabajar con datos relacionales.

tidy4a <- table4a %>% 
  pivot_longer(c(`1999`, `2000`), names_to = "year", values_to = "cases")
tidy4b <- table4b %>% 
  pivot_longer(c(`1999`, `2000`), names_to = "year", values_to = "population")

left_join(tidy4a, tidy4b)
## Joining, by = c("country", "year")
## # A tibble: 6 x 4
##   country     year   cases population
##   <chr>       <chr>  <int>      <int>
## 1 Afghanistan 1999     745   19987071
## 2 Afghanistan 2000    2666   20595360
## 3 Brazil      1999   37737  172006362
## 4 Brazil      2000   80488  174504898
## 5 China       1999  212258 1272915272
## 6 China       2000  213766 1280428583

Datos “anchos”

pivot_wider() (pivotar a lo ancho) es lo opuesto de pivot_longer(). Se usa cuando una observación aparece en múltiples filas. Por ejemplo, considera la tabla2: una observación es un país en un año, pero cada observación aparece en dos filas.

Para ordenar esto, primero analizamos la representación de un modo similar a cómo se haría con pivot_longer(). Esta vez, sin embargo, necesitamos únicamente dos parámetros:

La columna desde la que obtener los nombres de las variables. En este caso corresponde a type. La columna desde la que obtener los valores. En este caso corresponde a count.

Una vez resuelto esto, podemos usar pivot_wider(), como se muestra debajo.

table2 %>%
    pivot_wider(names_from = type, values_from = count)
## # A tibble: 6 x 4
##   country      year  cases population
##   <chr>       <int>  <int>      <int>
## 1 Afghanistan  1999    745   19987071
## 2 Afghanistan  2000   2666   20595360
## 3 Brazil       1999  37737  172006362
## 4 Brazil       2000  80488  174504898
## 5 China        1999 212258 1272915272
## 6 China        2000 213766 1280428583

Como te habrás dado cuenta a partir de sus nombres, las funciones pivot_longer() y pivot_wider() son complementarias. pivot_longer() genera tablas angostas y largas, pivot_wider() genera tablas anchas y cortas.

2. Separar y unir

Hasta ahora has aprendido a ordenar las tablas tabla2 y tabla4, pero no la tabla3, que tiene un problema diferente: tenemos una columna (rate) que contiene dos variables (casos y población).

Para solucionar este problema, necesitamos la función separate() (separar). También aprenderás acerca del complemento de separate(): unite() (unir), que se usa cuando una única variable se reparte en varias columnas.

Separar

separate() desarma una columna en varias columnas, dividiendo de acuerdo a la posición de un carácter separador. La columna rate contiene tanto los casos como la población, por lo que necesitamos dividirla en dos variables. La función separate()toma el nombre de la columna a separar y el nombre de las columnas a donde irá el resultado, tal como se muestra en el código a continuación.

table3 %>% 
  separate(rate, into = c("cases", "population"))
## # A tibble: 6 x 4
##   country      year cases  population
##   <chr>       <int> <chr>  <chr>     
## 1 Afghanistan  1999 745    19987071  
## 2 Afghanistan  2000 2666   20595360  
## 3 Brazil       1999 37737  172006362 
## 4 Brazil       2000 80488  174504898 
## 5 China        1999 212258 1272915272
## 6 China        2000 213766 1280428583

Por defecto, separate() dividirá una columna donde encuentre un carácter no alfanumérico (esto es, un carácter que no es un número o letra). Por ejemplo, en el siguiente código, separate() divide los valores de rate donde aparece una barra (/). Si deseas usar un carácter específico para separar una columna, puedes especificarlo en el argumento sep de separate().

Por ejemplo, el código anterior se puede re-escribir del siguiente modo:

table3 %>% 
  separate(rate, into = c("cases", "population"), sep = "/")
## # A tibble: 6 x 4
##   country      year cases  population
##   <chr>       <int> <chr>  <chr>     
## 1 Afghanistan  1999 745    19987071  
## 2 Afghanistan  2000 2666   20595360  
## 3 Brazil       1999 37737  172006362 
## 4 Brazil       2000 80488  174504898 
## 5 China        1999 212258 1272915272
## 6 China        2000 213766 1280428583

Mira atentamente los tipos de columna: notarás que cases y population son columnas de tipo carácter. Este es el comportamiento por defecto en separate(): preserva el tipo de columna. Aquí, sin embargo, no es muy útil, ya que se trata de números. Podemos pedir a separate() que intente convertir a un tipo más adecuado usando convert = TRUE:

table3 %>% 
  separate(rate, into = c("cases", "population"), convert = TRUE)
## # A tibble: 6 x 4
##   country      year  cases population
##   <chr>       <int>  <int>      <int>
## 1 Afghanistan  1999    745   19987071
## 2 Afghanistan  2000   2666   20595360
## 3 Brazil       1999  37737  172006362
## 4 Brazil       2000  80488  174504898
## 5 China        1999 212258 1272915272
## 6 China        2000 213766 1280428583

Unir

unite() es el inverso de separate(): combina múltiples columnas en una única columna. Necesitarás esta función con mucha menos frecuencia que separate(), pero aún así es una buena herramienta para conocer.

Podemos usar unite() para volver a unir las columnas que acabamos de separar.

Usamos col = rate para indicar que la nueva columna debe llamarse rate.

Ejercicios

Usando el set de datos “sida_mujeres_peru.csv”:

Convertir el dataset a un formato tidy

sida_mujeres <- read_csv ("data/sida_mujeres_peru.csv", col_types = "cccccc")
sida_mujeres
## # A tibble: 29 x 6
##    año   `De 0 a 14 años` `De 15 a 24 años` `De 25 a 49 años` `De 50 a 59 años`
##    <chr> <chr>            <chr>             <chr>             <chr>            
##  1 1990  2                9                 19                1                
##  2 1991  3                13                31                -                
##  3 1992  4                26                57                7                
##  4 1993  15               32                51                5                
##  5 1994  14               44                84                4                
##  6 1995  16               49                143               16               
##  7 1996  22               69                176               16               
##  8 1997  19               60                175               15               
##  9 1998  18               95                207               6                
## 10 1999  17               78                205               20               
## # … with 19 more rows, and 1 more variable: De 60 años y más <chr>
sida_mujeres %>% 
  pivot_longer(c(`De 0 a 14 años`, `De 15 a 24 años`, `De 25 a 49 años`,`De 50 a 59 años`, `De 60 años y más`), names_to = "gruposdedad", values_to = "cases")
## # A tibble: 145 x 3
##    año   gruposdedad      cases
##    <chr> <chr>            <chr>
##  1 1990  De 0 a 14 años   2    
##  2 1990  De 15 a 24 años  9    
##  3 1990  De 25 a 49 años  19   
##  4 1990  De 50 a 59 años  1    
##  5 1990  De 60 años y más 1    
##  6 1991  De 0 a 14 años   3    
##  7 1991  De 15 a 24 años  13   
##  8 1991  De 25 a 49 años  31   
##  9 1991  De 50 a 59 años  -    
## 10 1991  De 60 años y más -    
## # … with 135 more rows