1  R y el tidyverse

En la gran mayoría de las ejemplos y ejercicios de este libro vamos a usar una computadora (te quiero mucho Skynet ♥️). Con ella nos vamos a comunicar utilizando un lenguaje de programación muy popular en el campo de la estadística: R(R Core Team 2023). Por eso mi recomendación es que lo que primero tenés que hacer es instalar R y RStudio. RStudio es una interfaz muy popular utilizada para, mayormente, programar en R. En el recuadro siguiente van a encontrar información de cómo instalar ambas cosas.

R Core Team. 2023. R: A Language and Environment for Statistical Computing. Vienna, Austria: R Foundation for Statistical Computing. https://www.R-project.org/.
Instalación de R y RStudio

Lo primero que hay que hacer para poder correr scripts de R es, como resulta evidente, instalar R. Lo pueden hacer seleccionando su sistema operativo en este link y siguiendo los pasos de la instalación.

Pueden bajar la versión gratuita de RStudio del siguiente link. En caso de que el link no haya detectado correctamente el sistema operativo, en la sección All Installers pueden seleccionarlo manualmente. Una vez descargado el instalador sólo hay que seguir los pasos de la intalación.

Si bien la mayoría de las cosas que vamos a ahcer en este libro se pueden hacer con funciones de R base1, la propuesta es utilizar los paquetes y funciones del tidyverse. El tidyverse es una colección de paquetes diseñados para el campo de la ciencia de datos y que comparten una filosofía de diseño subyacente, una gramática y una estructura de datos(Wickham et al. 2019). Tranquilos que en la sección siguiente se va a ir aclarando la cosa.

1 Es decir, sin tener que cargar ningún paquete de funciones adicional.

1.1 Tidy data

Lo primero que tenemos que pensar cuando trabajamos con el tidyverse es que nuestros datos estén en formato tidy. ¿Qué significa esto? Cuando un dataset está en formato tidy, cada columna corresponde a una variable y cada fila a una única observación2. Veamos un ejemplo. Tenemos tres sujetos a los cuales les medimos el tiempo de respuesta en una tarea. Cada sujeto realiza dos repeticiones de esta medición, el trial 1 y el trial 2. En la tabla Tabla 1.1 podemos ver las dos formas de organizar esta información.

2 El caso contrario sería en el que una fila contiene varios mediciones para distintos niveles de una variable. Este formato se conoce como wide.

Tabla 1.1: Ejemplo de tablas tidy y wide.
(a) Tidy
sujeto trial tiempo_respuesta
Jerry 1 0.0807501
Jerry 2 0.8343330
Elaine 1 0.6007609
Elaine 2 0.1572084
George 1 0.0073994
George 2 0.4663935
(b) Wide
sujeto trial_1 trial_2
Jerry 0.4977774 0.7725215
Elaine 0.2897672 0.8746007
George 0.7328820 0.1749406

A lo largo de este capítulo iremos viendo los beneficios de almacenar los datos en formato tidy. Por supuesto que estas ventajas tienen su precio, principalemente que las bases de datos crecen mucho en tamaño si tenemos muchas medidas repetidas con distintos valores de las variables.

1.2 Introducción al Tidyverse

Como contamos más arriba, el tidyverse es una colección cerca de 25 paquetes, todos relacionados con la carga, manejo, modificación y visualización de datos. La idea de este libro no es profundizar en todas sus capacidades pero consideramos importante presentar algunas de las funciones que más vamos a utilizar a lo largo del libro. Estas son funciones para leer datos del paquete {readr}, los verbos de {dplyr} para manipularlos, las funciones de {tidyR} para acomodarlos y el poderosísimo {ggplot2} para visualizarlos.

1.2.1 Cargando datos con readr

Una de las cosas que vamos a hacer más a menudo en este libro es cargar algún dataset. Para esto vamos a usar varias de las funcionalidades del paquete {readr}.

El caso más simple al que nos vamos a enfrentar es la carga de una base de datos organizada en columnas y separadas por comas en un archivo de extensión .csv. En este caso lo que tenemos que hacer es bastante simple, usar la función read_csv() como a continuación:

Ver el código
summer <- read_csv("../data/summer.csv")

Podemos ver que al cargar los datos read_csv nos dice que hay ocho columnas chr (o sea de texto) y una dbl (o sea, un número). Si usamos la función summary podemos ver un detalle de cada avriable con su tipo y alguna descripción3:

3 Existen alternativas para visualizar rápidamente un conjunto de datos como str o glimpse o la función skim del paquete {skimr}.

Ver el código
summary(summer)
#>       Year          City              Sport            Discipline       
#>  Min.   :1896   Length:31165       Length:31165       Length:31165      
#>  1st Qu.:1948   Class :character   Class :character   Class :character  
#>  Median :1980   Mode  :character   Mode  :character   Mode  :character  
#>  Mean   :1970                                                           
#>  3rd Qu.:2000                                                           
#>  Max.   :2012                                                           
#>    Athlete            Country             Gender             Event          
#>  Length:31165       Length:31165       Length:31165       Length:31165      
#>  Class :character   Class :character   Class :character   Class :character  
#>  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
#>                                                                             
#>                                                                             
#>                                                                             
#>     Medal          
#>  Length:31165      
#>  Class :character  
#>  Mode  :character  
#>                    
#>                    
#> 

Los datos adentro de summer.csv son los ganadores de medallas en los juegos olímpicos de verano. Podemos ver algunas filas de muestra:

Ver el código
head(summer)
#> # A tibble: 6 × 9
#>    Year City   Sport    Discipline Athlete               Country Gender
#>   <dbl> <chr>  <chr>    <chr>      <chr>                 <chr>   <chr> 
#> 1  1896 Athens Aquatics Swimming   HAJOS, Alfred         HUN     Men   
#> 2  1896 Athens Aquatics Swimming   HERSCHMANN, Otto      AUT     Men   
#> 3  1896 Athens Aquatics Swimming   DRIVAS, Dimitrios     GRE     Men   
#> 4  1896 Athens Aquatics Swimming   MALOKINIS, Ioannis    GRE     Men   
#> 5  1896 Athens Aquatics Swimming   CHASAPIS, Spiridon    GRE     Men   
#> 6  1896 Athens Aquatics Swimming   CHOROPHAS, Efstathios GRE     Men   
#> # ℹ 2 more variables: Event <chr>, Medal <chr>

El formato en el que read_csv almacena los datos se llama tibble y es el formato por excelencia del tidyverse. De momento lo único que nos importa es que es un formato que almacena los casos en filas y las variables en columnas (cada variable tiene un formato). Para más información sobre las cualidades de este formato, les recomiendo revisar la documentación.

1.2.2 El operador pipe (|>) del paquete {magrittr}

El operador pipe nos permite concatenar funciones que utilizan como entrada los mismos datos. El principio de operación es el siguiente, supongan que nosotros queremos cargar un dataset y aplicarle la función summary. Esto lo podemos hacer simplemente cargando el dataset en una lìnea de código y ejecutanco la función summary() en la siguiente.

Ver el código
data <- read_csv("../data/summer.csv")
summary(data)
#>       Year          City              Sport            Discipline       
#>  Min.   :1896   Length:31165       Length:31165       Length:31165      
#>  1st Qu.:1948   Class :character   Class :character   Class :character  
#>  Median :1980   Mode  :character   Mode  :character   Mode  :character  
#>  Mean   :1970                                                           
#>  3rd Qu.:2000                                                           
#>  Max.   :2012                                                           
#>    Athlete            Country             Gender             Event          
#>  Length:31165       Length:31165       Length:31165       Length:31165      
#>  Class :character   Class :character   Class :character   Class :character  
#>  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
#>                                                                             
#>                                                                             
#>                                                                             
#>     Medal          
#>  Length:31165      
#>  Class :character  
#>  Mode  :character  
#>                    
#>                    
#> 

Pero, también podemos aprovechar el operador pipe y hacer todo en una única línea de código.

Ver el código
read_csv("../data/summer.csv") |> summary()
#>       Year          City              Sport            Discipline       
#>  Min.   :1896   Length:31165       Length:31165       Length:31165      
#>  1st Qu.:1948   Class :character   Class :character   Class :character  
#>  Median :1980   Mode  :character   Mode  :character   Mode  :character  
#>  Mean   :1970                                                           
#>  3rd Qu.:2000                                                           
#>  Max.   :2012                                                           
#>    Athlete            Country             Gender             Event          
#>  Length:31165       Length:31165       Length:31165       Length:31165      
#>  Class :character   Class :character   Class :character   Class :character  
#>  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
#>                                                                             
#>                                                                             
#>                                                                             
#>     Medal          
#>  Length:31165      
#>  Class :character  
#>  Mode  :character  
#>                    
#>                    
#> 

Al dejar vacío el paréntesis de la función summary(), la misma va a tomar como variable de entrada a la que está antes del operador pipe, es decir, a la que antes llamamos data. En el caso que la función summary() tuviera más de una variable de entrada, lo que viene antes del pipe tomaría el lugar de la primera de ellas.

Si bien esta funcionalidad parece algo que complica las cosas y que no trae demasiados beneficios con un ejemplo tan simple, más adelante veremos que puede ser de gran utilidad, ayudando a disminuir la cantidad de línes de código y de variables intermedias.

1.2.3 {dplyr} y sus verbos

Una de las cosas más útiles del tidyverse para el tipo de procesamiento de datos que vamos a llevar a cabo en este libro son los verbos de dplyr. Estas funciones no permiten agregar columnas, resumir la información, filtrar filas, seleccionar columnas, etc4. Y todas estas acciones las podemos hacer en la base de datos completa o en una parte de ella agrupada de acuerdo a algún criterio. Vayamos de a poco.

4 Para más detalles sobre los verbos disponibles en el paquete {dplyr} pueden visital este la página de referencia.

1.2.3.1 El verbo filter

Volvamos a los datos de los JJOO de verano. Supongamos que nos queremos quedar sólo con las medallas de Argentina. Para este tipo de filtrado de filas (o casos, o mediciones) {dplyr} tiene un verbo que se llama filter y funciona de la siguiente forma5:

5 Se preguntarán por qué antes de la función filter aparece un ::dplyr. Esto es simplemente una forma de decirle a R que la función filter que debe utilizar es la del paquete {dplyr}. Esta es una práctica recomendable sobre todo para funciones con nombres comunes como filter o select.

Ver el código
summer |> dplyr::filter(Country == "ARG") |> head(10)
#> # A tibble: 10 × 9
#>    Year City  Sport     Discipline Athlete          Country Gender
#>   <dbl> <chr> <chr>     <chr>      <chr>            <chr>   <chr> 
#> 1  1924 Paris Athletics Athletics  BRUNETO, Luis    ARG     Men   
#> 2  1924 Paris Boxing    Boxing     PORZIO, Alfredo  ARG     Men   
#> 3  1924 Paris Boxing    Boxing     QUARTUCCI, Pedro ARG     Men   
#> 4  1924 Paris Boxing    Boxing     COPELLO, Alfredo ARG     Men   
#> 5  1924 Paris Boxing    Boxing     MENDEZ, Hector   ARG     Men   
#> 6  1924 Paris Polo      Polo       KENNY, Arturo    ARG     Men   
#> # ℹ 4 more rows
#> # ℹ 2 more variables: Event <chr>, Medal <chr>

Noten que estamos utilizando el operador |> para concatenar las acciones: Con los datos de summer hacemos el filtrado y, luego, mostramos las primeras diez filas de esos datos ya filtrados.

También podríamos quere quedarnos con las medallas de Argenitna en los JJOO de Atenas 2004, para esto debemos el operador lógico “y”, cuyo símbolo en R es &:

Ver el código
summer |> dplyr::filter(Country == "ARG" & Year == 2004) |> head(5)
#> # A tibble: 5 × 9
#>    Year City   Sport      Discipline Athlete                   Country Gender
#>   <dbl> <chr>  <chr>      <chr>      <chr>                     <chr>   <chr> 
#> 1  2004 Athens Aquatics   Swimming   BARDACH, Georgina         ARG     Women 
#> 2  2004 Athens Basketball Basketball DELFINO, Carlos Francisco ARG     Men   
#> 3  2004 Athens Basketball Basketball FERNANDEZ, Gabriel Diego  ARG     Men   
#> 4  2004 Athens Basketball Basketball GINOBILI, Emanuel David   ARG     Men   
#> 5  2004 Athens Basketball Basketball GUTIERREZ, Leonardo Mart… ARG     Men   
#> # ℹ 2 more variables: Event <chr>, Medal <chr>

Que linda esa Generación Dorada🏅, ¿No?.Por otro lado, si nos queremos quedar con las medallas de Argentina o Brasil debemos utilizar el operador lógico “o”, cuyo símbolo en R es |:

Ver el código
summer |> dplyr::filter(Country == "ARG" | Country == "BRA") |> head(10)
#> # A tibble: 10 × 9
#>    Year City    Sport    Discipline Athlete                   Country Gender
#>   <dbl> <chr>   <chr>    <chr>      <chr>                     <chr>   <chr> 
#> 1  1920 Antwerp Shooting Shooting   PARAENSE, Guilherme       BRA     Men   
#> 2  1920 Antwerp Shooting Shooting   BARBOSA, Dario            BRA     Men   
#> 3  1920 Antwerp Shooting Shooting   DA COSTA, Afranio Antonio BRA     Men   
#> 4  1920 Antwerp Shooting Shooting   PARAENSE, Guilherme       BRA     Men   
#> 5  1920 Antwerp Shooting Shooting   SOLEDADE, Fernando        BRA     Men   
#> 6  1920 Antwerp Shooting Shooting   WOLF, Sebastiao           BRA     Men   
#> # ℹ 4 more rows
#> # ℹ 2 more variables: Event <chr>, Medal <chr>

Aunque, una alternativa muy útil cuando tenemos los valores de una variable que queremos filtrar en un array es:

Ver el código
summer |> dplyr::filter(Country %in% c("ARG", "BRA")) |> head(10)
#> # A tibble: 10 × 9
#>    Year City    Sport    Discipline Athlete                   Country Gender
#>   <dbl> <chr>   <chr>    <chr>      <chr>                     <chr>   <chr> 
#> 1  1920 Antwerp Shooting Shooting   PARAENSE, Guilherme       BRA     Men   
#> 2  1920 Antwerp Shooting Shooting   BARBOSA, Dario            BRA     Men   
#> 3  1920 Antwerp Shooting Shooting   DA COSTA, Afranio Antonio BRA     Men   
#> 4  1920 Antwerp Shooting Shooting   PARAENSE, Guilherme       BRA     Men   
#> 5  1920 Antwerp Shooting Shooting   SOLEDADE, Fernando        BRA     Men   
#> 6  1920 Antwerp Shooting Shooting   WOLF, Sebastiao           BRA     Men   
#> # ℹ 4 more rows
#> # ℹ 2 more variables: Event <chr>, Medal <chr>

Finalmente, si tenemos una variable numérica, podemos filtrar con condiciones como mayor o menor:

Ver el código
summer |> dplyr::filter(Year > 2010) |> head(5)
#> # A tibble: 5 × 9
#>    Year City   Sport    Discipline Athlete          Country Gender
#>   <dbl> <chr>  <chr>    <chr>      <chr>            <chr>   <chr> 
#> 1  2012 London Aquatics Diving     BOUDIA, David    USA     Men   
#> 2  2012 London Aquatics Diving     QIU, Bo          CHN     Men   
#> 3  2012 London Aquatics Diving     DALEY, Thomas    GBR     Men   
#> 4  2012 London Aquatics Diving     CHEN, Ruolin     CHN     Women 
#> 5  2012 London Aquatics Diving     BROBEN, Brittany AUS     Women 
#> # ℹ 2 more variables: Event <chr>, Medal <chr>

1.2.3.2 El verbo select

El verbo select es similar a filter pero nos permite filtrar no casos sino variables. Por ejemplo, ¿Qué pasa si solo nos interesa el año, la ciudad y el nombre del atleta?:

Ver el código
summer |> dplyr::select(c(Year, City, Athlete)) |> head(5)
#> # A tibble: 5 × 3
#>    Year City   Athlete           
#>   <dbl> <chr>  <chr>             
#> 1  1896 Athens HAJOS, Alfred     
#> 2  1896 Athens HERSCHMANN, Otto  
#> 3  1896 Athens DRIVAS, Dimitrios 
#> 4  1896 Athens MALOKINIS, Ioannis
#> 5  1896 Athens CHASAPIS, Spiridon

1.2.3.3 El verbo mutate

Ahora las cosas se complican un poco. mutate es un verbo que nos permite crear nuevas columnas ya sea con datos nuevos o en función de los datos existentes. Por ejemplo, creemos una columna nueva que tenga un chr con el país, un guión y el nombre del atleta y llamémosla nationality_athlete. Nos vamos a quedar sólo con el año, la medalla que ganó y el nuevo nombre combinado con la nacionalidad:

Ver el código
summer |> 
  dplyr::mutate(nationality_athlete = paste(Country, "-", Athlete)) |> 
  dplyr::select(c(Year, Medal, nationality_athlete)) |>
  head(5)
#> # A tibble: 5 × 3
#>    Year Medal  nationality_athlete     
#>   <dbl> <chr>  <chr>                   
#> 1  1896 Gold   HUN - HAJOS, Alfred     
#> 2  1896 Silver AUT - HERSCHMANN, Otto  
#> 3  1896 Bronze GRE - DRIVAS, Dimitrios 
#> 4  1896 Gold   GRE - MALOKINIS, Ioannis
#> 5  1896 Silver GRE - CHASAPIS, Spiridon

O, por ejemplo, podemos querer crear una variable que nos ponga un \(1\) si es griego y un \(0\) si no6:

6 Para más detalles sobre la función if_else pueden ver el siguiente link.

Ver el código
summer |> 
  dplyr::mutate(is_greek = if_else(Country == "GRE", 1, 0)) |> 
  dplyr::select(c(Year, Medal, Country, is_greek)) |>
  head(5)
#> # A tibble: 5 × 4
#>    Year Medal  Country is_greek
#>   <dbl> <chr>  <chr>      <dbl>
#> 1  1896 Gold   HUN            0
#> 2  1896 Silver AUT            0
#> 3  1896 Bronze GRE            1
#> 4  1896 Gold   GRE            1
#> 5  1896 Silver GRE            1

Ahora vamos a aprender algo muy importante y cool 🆒: A agrupar los casos de acuerdo a una variable. Por ejemplo, si queremos agregar una columna que contenga la cantidad total de medallas ganadas por un país a cada atleta de ese país podemos hacer lo siguiente:

Ver el código
summer |> 
  group_by(Country) |>
  dplyr::mutate(num_medals = n()) |> 
  dplyr::select(c(Year, Medal, Athlete, num_medals)) |>
  head(5)
#> # A tibble: 5 × 5
#> # Groups:   Country [3]
#>   Country  Year Medal  Athlete            num_medals
#>   <chr>   <dbl> <chr>  <chr>                   <int>
#> 1 HUN      1896 Gold   HAJOS, Alfred            1079
#> 2 AUT      1896 Silver HERSCHMANN, Otto          146
#> 3 GRE      1896 Bronze DRIVAS, Dimitrios         148
#> 4 GRE      1896 Gold   MALOKINIS, Ioannis        148
#> 5 GRE      1896 Silver CHASAPIS, Spiridon        148

¿Perdidos? Tomensé su tiepo para tratar de entender qué pasó y prueben distintas alternativas en sus computadoras.

1.2.3.4 El verbo summarise

Por último, el verbo summarise nos permite sacar medidas resumen de nuestros datos. Empecemos con algo obvio: ¿Cuántas medallas de oro ganó cada país en la historia de los juegos olímpicos?. Podemos hacer algo parecido a lo último que hicimos con mutate pero el resultados será ligeramente diferente7:

7 La función arrange nos ordena los datos de acuerdo a la variable que le enviemos como parámetro de menos a mayor. Si queremos que ordene de mayor a menor debemos agregar la función desc en el argumento. Más detalles acá.

Ver el código
summer |> 
  dplyr::filter(Medal == "Gold") |>
  group_by(Country) |>
  dplyr::summarise(num_medals = n()) |>
  arrange(desc(num_medals)) |>
  head(10)
#> # A tibble: 10 × 2
#>   Country num_medals
#>   <chr>        <int>
#> 1 USA           2235
#> 2 URS            838
#> 3 GBR            546
#> 4 ITA            476
#> 5 GER            452
#> 6 HUN            412
#> # ℹ 4 more rows

Hay algo raro, ¿No? Bueno, sí, de esta forma estamos contando a todos los atletas que tuvieron la misma medalla (por ejemplo, si la medalla fue por fútbol estamos contando cerca de 30 medallas). Para resolver esto nos podemos sacar de encima los casos duplicados por año, deporte, disciplina, evento y género8:

8 La función distinct nos conserva una sola realización de cada caso que es igual de acuerdo a las variables que le pasemos como parámetros. Más detalles acá.

Ver el código
summer |> 
  distinct(Year, Sport, Discipline, Event, Gender, .keep_all = TRUE) |>
  dplyr::filter(Medal == "Gold") |>
  group_by(Country) |>
  dplyr::summarise(num_medals = n()) |>
  arrange(desc(num_medals)) |>
  head(5)
#> # A tibble: 5 × 2
#>   Country num_medals
#>   <chr>        <int>
#> 1 USA             67
#> 2 GBR             46
#> 3 CHN             40
#> 4 RUS             22
#> 5 GER             19

Vayamos con lo último, calculemos la media y la desviación estándar de las medallas de Argentina por JJOO combinando todo lo que vimos.

Ver el código
summer |> 
  distinct(Year, Sport, Discipline, Event, Medal, Gender, .keep_all = TRUE) |>
  dplyr::filter(Country == "ARG") |>
  group_by(Country, Year) |>
  dplyr::summarise(num_medals = n()) |>
  ungroup() |>
  summarise(media  = mean(num_medals),
            desvio = sd(num_medals))
#> # A tibble: 1 × 2
#>   media desvio
#>   <dbl>  <dbl>
#> 1  3.83   2.28

Digieran esto tranquilos.

1.2.4 {tidyR}, el paquete para ordenar tus datos

El paquete {tidyR} tiene muchas herramientas de manejo de tablas como reformatear, expandir tablas, manejar valores faltantes, dividir celdas, anidar datos, etc9. Sin embargo, en esta breve introducción sólo vamos a presentar muy brevemente las herramientas que nos permiten convertir una tabla wide en tidy (o long) y viceverse.

9 Para más información ver el cheatsheet.

1.2.4.1 La función pivot_longer

Volvamos a la tabla iniicial que teníamos en formato wide:

Ver el código
tabla_wide <- tibble(sujeto  = rep(c("Jerry", "Elaine", "George")),
                     trial_1 = runif(3),
                     trial_2 = runif(3)) 

tabla_wide
#> # A tibble: 3 × 3
#>   sujeto trial_1 trial_2
#>   <chr>    <dbl>   <dbl>
#> 1 Jerry    0.320  0.404 
#> 2 Elaine   0.402  0.0637
#> 3 George   0.196  0.389

Si nosotros quisiñeramos transformar esta tabla en una tabla en formato tidy podemos utilizar la función pivot_longer10. Veamos como funciona y después la desmenuzamos:

10 Más información acá.

Ver el código
pivot_longer(data = tabla_wide, 
             cols = trial_1:trial_2, 
             names_to = "trial",
             values_to = "tiempo_respuesta")
#> # A tibble: 6 × 3
#>   sujeto trial   tiempo_respuesta
#>   <chr>  <chr>              <dbl>
#> 1 Jerry  trial_1           0.320 
#> 2 Jerry  trial_2           0.404 
#> 3 Elaine trial_1           0.402 
#> 4 Elaine trial_2           0.0637
#> 5 George trial_1           0.196 
#> 6 George trial_2           0.389

Los argumentos son los siguientes: data es la tabla a la que le vamos a realizar el cambio de formato; cols son las columnas que vamos a cambiar, en este caso desde trial_1 a trial_2; en names_to indicamos la variable a la que vamos a mandar los nombres de las columnas actuales; y values_to la variables a la que vamos a mandar los valores.

Algo ligeramente raro es que la columna trial no es numérica y, sólo por completitud, lo vamos a solucionar usando a nuestro gran amigo |> y al verbo mutate11:

11 Y la función parse_number del paquete {readr}.

Ver el código
pivot_longer(data = tabla_wide, 
             cols = trial_1:trial_2, 
             names_to = "trial",
             values_to = "tiempo_respuesta") |>
  mutate(trial = parse_number(trial))
#> # A tibble: 6 × 3
#>   sujeto trial tiempo_respuesta
#>   <chr>  <dbl>            <dbl>
#> 1 Jerry      1           0.320 
#> 2 Jerry      2           0.404 
#> 3 Elaine     1           0.402 
#> 4 Elaine     2           0.0637
#> 5 George     1           0.196 
#> 6 George     2           0.389

1.2.4.2 La función pivot_wider

Ahora vamos con el caso contrario en el que tenemos una tabla en formato long y la queremos convertir en wide:

Ver el código
tabla_long <- pivot_longer(data = tabla_wide, 
                           cols = trial_1:trial_2, 
                           names_to = "trial",
                           values_to = "tiempo_respuesta") |>
  mutate(trial = parse_number(trial))

tabla_long
#> # A tibble: 6 × 3
#>   sujeto trial tiempo_respuesta
#>   <chr>  <dbl>            <dbl>
#> 1 Jerry      1           0.320 
#> 2 Jerry      2           0.404 
#> 3 Elaine     1           0.402 
#> 4 Elaine     2           0.0637
#> 5 George     1           0.196 
#> 6 George     2           0.389

Para esto vamos a hechar mano a la función pivot_wider12 que tiene una sintáxis parecida a su prima pivot_longer:

12 Más información acá.

Ver el código
pivot_wider(data = tabla_long, 
            names_from = trial, 
            values_from = tiempo_respuesta)
#> # A tibble: 3 × 3
#>   sujeto   `1`    `2`
#>   <chr>  <dbl>  <dbl>
#> 1 Jerry  0.320 0.404 
#> 2 Elaine 0.402 0.0637
#> 3 George 0.196 0.389

Et Voilà!, ya tenemos nuestra tabla en formato wide. En este caso le dijimos de que variable tomar los nombres de las nuevas columnas en names_from y de que variable tomar los valores en values_from.

Finalmente, y sólo para alimnetar nuestra obsesión, vamos a corregir los nombres de las columnas agregando el prefijo trial_ utilizando el parámetro de la función names_prefix:

Ver el código
pivot_wider(data = tabla_long, 
            names_from = trial, 
            names_prefix = "trial_",
            values_from = tiempo_respuesta)
#> # A tibble: 3 × 3
#>   sujeto trial_1 trial_2
#>   <chr>    <dbl>   <dbl>
#> 1 Jerry    0.320  0.404 
#> 2 Elaine   0.402  0.0637
#> 3 George   0.196  0.389

1.3 Algunas palabras finales

Como vimos brevemente en este capítulo, los paquetes del tidyverse son una herramineta importantísima para el análisis de datos utilizando R. Para más detalles sobre estas funcionalidades les recomendamos la guía de Hadley Wickham(Wickham et al. 2019) o, si ya se quieren sumergir de lleno en el mundo del análisis de datos con R, este fantástico libro (Wickham, Çetinkaya-Rundel, y Grolemund 2023)13. Es decir, sin tener que cargar ningún paquete de funciones adicional..

Wickham, Hadley, Mara Averick, Jennifer Bryan, Winston Chang, Lucy D’Agostino McGowan, Romain François, Garrett Grolemund, et al. 2019. «Welcome to the Tidyverse». Journal of open source software 4 (43): 1686.
Wickham, Hadley, Mine Çetinkaya-Rundel, y Garrett Grolemund. 2023. R for data science. " O’Reilly Media, Inc.".

13 Disponible gratis online en acá.