Manejo de datos con R (I):
the tidyverse way

Módulo práctico de ITA
(Grupo M)

Data munging: the tidyverse way



Aprendimos a cargar datos, pero es raro que los datos estén preparados para empezar nuestro análisis, así que hay que “arreglar/limpiar” los datos. Para ello, tenemos que:

  1. Hacer nuestros datos TIDY

  2. Arreglarlos/modificarlos para que sean útiles para nuestros propósitos

Arreglando los datos

  • Aprenderemos a limpiar y transformar datos en R. Priorizaremos la nueva forma de hacer las cosas en R (o workflow) conocido como tidyverse.


  • El procesado/limpieza de los datos suele ocupar un 80% del tiempo de un análisis de datos; así que el workflow sería más bien así:

¿qué es el tidyverse?

  • Un conjunto de paquetes que trabajan en armonía y que permiten una nueva forma de escribir/programar en R.

principales pkgs del Tidyverse

  • tidyr: convertir a tidy data

  • dplyr: para manipular datos

  • ggplot2: para hacer gráficos

  • … y algunos más

nos centraremos principalmente en dos paquetes: dplyr y ggplot2

“Filosofía” del Tidyverse

Dos principios del tidyverse:

  • Los scripts deben ser “fácilmente” legibles por las personas

  • Resolver problemas complejos encadenando funciones simples con el operador pipe (%>%)


El operador %>% es crucial en el tidyverse

  • El operador pipe se lo debemos a Stefan Bache que lo introdujo en 2014 en su pkg magrittr
  • The pipe ha tenido tanto éxito que en 2021 apareció una nueva pipe en R-base: |>

  • Puedes leer sobre ella aquí

The pipe ( %>% )



  • El operador %>% es crucial en el tidyverse. Hay que saber usarlo y entenderlo

  • Es fácil. Pronto os sentiréis cómodos con él.

The pipe

  • The pipe es un operador que pasa el elemento que está a su izquierda como un argumento de la función que tiene a la derecha.



Igual os resulta más fácil entenderlo con ejemplos

  • Las siguientes 2 expresiones hacen exactamente lo mismo:
head(iris, n = 4)         #- forma habitual de llamar/usar la función head()

iris %>% head(. , n = 4)  #- usando el operador pipe

The pipe (más ejemplos)

  • Estas 3 expresiones también son equivalentes, hacen exactamente lo mismo:
head(iris, n = 4)         #- forma habitual de llamar/usar la función head()

iris %>% head(. , n = 4)  #- usando el operador pipe (con el punto actuando como placeholder)

iris %>% head(n = 4)      #- usando el operador pipe (SIN el punto)

¿Qué hace la siguiente expresión?

4 %>% head(iris, .)

¿por qué no funciona la siguiente expresión?

4 %>% head(iris)

Intenta descubrir/entender que hace la siguiente expresión:

letters %>% paste0( "-----" ,  .  ,  "!!!" ) %>% toupper

Tidy data



  • Para trabajar à la tidyverse es crucial que los datos sean “tidy”
  • El concepto de datos tidy es sencillo. Hacer los datos tidy no tanto pero tenemos un paquete para hacerlo fácil: el pkg tidyr

Un aspecto importante del tidyverse es hacer los datos tidy

  • Unos datos son tidy si: (1) cada columna es una variable, (2) cada fila es una observación y (3) cada valor está en, o tiene, su propia celda.

Parece fácil, y lo es: realmente es la situación a la que estamos acostumbrados, pero …
… mejor desarrollarlo con unos ejemplos

Tidy data … ejemplo I

¿Estos datos son tidy?

df_1 <- data.frame(
            year  = c("2014", "2015", "2016"),  
            Pedro = c(100, 500, 200), 
            Carla = c(400, 600, 250), 
            María = c(200, 700, 900)  )
DT::datatable(df_1)

Tidy data … ejemplo II

¿Estos datos son tidy?

df_2 <- data.frame(names = c("Pedro", "Carla", "María"), 
                      W_2014 = c(100, 400, 200), 
                      W_2015 = c(500, 600, 700),
                      W_2016 = c(200, 250, 900)   )
knitr::kable(df_2)
names W_2014 W_2015 W_2016
Pedro 100 500 200
Carla 400 600 250
María 200 700 900

Tidy data … ejemplo III

¿Estos datos son tidy?

df_3 <- data.frame(
            names =rep(c("Pedro", "Carla", "María"), times = 3),  
            year = rep(c("2014", "2015", "2016"), each = 3),
            salario = c(100, 400, 200, 500, 600, 700, 200, 250,900) )
gt::gt(df_3)
names year salario
Pedro 2014 100
Carla 2014 400
María 2014 200
Pedro 2015 500
Carla 2015 600
María 2015 700
Pedro 2016 200
Carla 2016 250
María 2016 900
  • Sí, estos sí son datos tidy

  • Son más difíciles de leer por los humanos, pero es que los datos los leen las máquinas!!

Los datos tidy suelen estar en formato largo o long

Tidy data en formato LONG



  • Para trabajar à la tidyverse es crucial que los datos sean “tidy”(en formato LONG)

  • Es importante aprender a pasar de datos WIDE a LONG y viceversa

  • Con el pkg tidyr es sencillo pero …

De wide a LONG format con … tidyr::pivot_longer()


Tarea: convierte “df_wide” a formato LARGO

Aquí tienes un df en formato ANCHO, pásalo a formato LARGO

df_wide <- data.frame(students = c("Pedro", "Carla", "María"), 
                        w_2014 = c(100, 400, 200), 
                        w_2015 = c(500, 600, 700),
                        w_2016 = c(200, 250, 900) )

Está en formato ancho:

knitr::kable(df_wide)
students w_2014 w_2015 w_2016
Pedro 100 500 200
Carla 400 600 250
María 200 700 900

Lo quiero en formato largo:

gt::gt(df_long)
students name value
Pedro w_2014 100
Pedro w_2015 500
Pedro w_2016 200
Carla w_2014 400
Carla w_2015 600
Carla w_2016 250
María w_2014 200
María w_2015 700
María w_2016 900
  • Te ayudará visualizar df_wide y ver que columnas contienen valores de la misma variable

  • Tienes que usar tidyr::pivot_longer() y en su primer argumento le tienes que decir que columnas hay que convertir a formato “largo”

#- la función pivot_longer() transforma los datos de formato ancho(wide) a formato largo(long)
library(tidyverse)

df_long <- df_wide %>% 
             tidyr::pivot_longer(cols = 2:4)

knitr::kable(df_long)
students name value
Pedro w_2014 100
Pedro w_2015 500
Pedro w_2016 200
Carla w_2014 400
Carla w_2015 600
Carla w_2016 250
María w_2014 200
María w_2015 700
María w_2016 900
#- la función pivot_longer() transforma los datos de formato ancho(wide) a formato largo(long)
df_long <- df_wide %>% 
             tidyr::pivot_longer(cols = 2:4, 
                                 names_to = "periodo", 
                                 values_to = "salario")
knitr::kable(df_long)
students periodo salario
Pedro w_2014 100
Pedro w_2015 500
Pedro w_2016 200
Carla w_2014 400
Carla w_2015 600
Carla w_2016 250
María w_2014 200
María w_2015 700
María w_2016 900

De long a WIDE format con tidyr::pivot_wider()

¿Por qué querríamos convertirlo a formato ANCHO?

Tarea: convierte “df_long” a formato ANCHO

  • df_long está en formato LARGO, pásalo a formato ANCHO

  • Tienes que distribuir los datos de salario en columnas: una columna para cada año

Está en formato largo:

gt::gt(df_long)
students periodo salario
Pedro w_2014 100
Pedro w_2015 500
Pedro w_2016 200
Carla w_2014 400
Carla w_2015 600
Carla w_2016 250
María w_2014 200
María w_2015 700
María w_2016 900

Lo quiero en formato ancho: (con una columna para cada año)

students w_2014 w_2015 w_2016
Pedro 100 500 200
Carla 400 600 250
María 200 700 900
  • Tienes que usar tidyr::pivot_wider()


  • En el argumento values_from le tienes que decir qué columna quieres que sus valores se distribuyan entre varias columnas


  • En el argumento names_from le tienes que decir qué columna quieres que sus valores aparezcan como los títulos de las nuevas columnas que se crearán
df_wide2 <- df_long %>% 
              tidyr::pivot_wider(values_from = salario,  
                                 names_from = periodo)
knitr::kable(df_wide2)
students w_2014 w_2015 w_2016
Pedro 100 500 200
Carla 400 600 250
María 200 700 900

Tarea: convierte OTRA VEZ “df_long” a formato ANCHO

  • df_long está en formato LARGO, pásalo a formato ANCHO

  • Tienes que distribuir los datos de salario en columnas: PERO esta vez quiero que haya una columna para cada persona (Pedro, Carla, …)

Está en formato largo:

gt::gt(df_long)
students periodo salario
Pedro w_2014 100
Pedro w_2015 500
Pedro w_2016 200
Carla w_2014 400
Carla w_2015 600
Carla w_2016 250
María w_2014 200
María w_2015 700
María w_2016 900

Lo quiero en formato ancho:

(con una columna para cada PERSONA)

periodo Pedro Carla María
w_2014 100 400 200
w_2015 500 600 700
w_2016 200 250 900
  • Tienes que usar tidyr::pivot_wider()


  • En el argumento values_from le tienes que decir qué columna quieres que sus valores se distribuyan entre varias columnas


  • CUIDADO!!! En el argumento names_from le tienes que decir qué columna quieres que sus valores aparezcan como los títulos de las nuevas columnas que se crearán
df_wide2 <- df_long %>% 
              tidyr::pivot_wider(values_from = salario, 
                                 names_from = students)
knitr::kable(df_wide2)
periodo Pedro Carla María
w_2014 100 400 200
w_2015 500 600 700
w_2016 200 250 900

Dos funciones más de tidyr



  • El paquete tidyr tiene muchas funciones. Veremos dos: separate() y unite()

las funciones separate() y unite()


  • separate() y unite() nos facilitarán poder separar y unir columnas


  • Por ejemplo, fíjate en el siguiente dataframe: ¿es tidy?
personajes year
Pedro Navaja 1978
Bob Dylan 1941
Peter Pan 1904

Tarea: Utilizando tidyr::separate()

  • Separa la columna personajes en dos columnas: nombre y apellido
personajes year
Pedro Navaja 1978
Bob Dylan 1941
Peter Pan 1904
  • Has de usar tidyr::separate()


  • Tendrás que darle los valores de 3 argumentos: col, into y sep

    • en el argumento col tienes que decir qué columna quieres separar

    • en into tienes que decir qué nombres quieres que tengan las nuevas columnas

    • en sep tienes que decir qué caracter separa los dos elementos

df_1 <- df %>% 
  tidyr::separate(col = personajes, 
                  into = c("nombre", "apellido"), 
                  sep = " ")


knitr::kable(df)
personajes year
Pedro Navaja 1978
Bob Dylan 1941
Peter Pan 1904
knitr::kable(df_1)
nombre apellido year
Pedro Navaja 1978
Bob Dylan 1941
Peter Pan 1904

Tarea: Utilizando tidyr::unite()

  • Unir las columnas nombre y apellido en una sola columna
nombre apellido year
Pedro Navaja 1978
Bob Dylan 1941
Peter Pan 1904
  • Has de usar tidyr::unite()


  • Tendrás que darle los valores de “3” argumentos:

    • en el argumento col tienes que decir el nombre de la nueva columna que se va a crear

    • después tienes que decir qué columnas quieres unir

    • en sep tienes que decir qué carácter separará los dos elementos que vamos a unir

df_2 <- df %>% 
       unite(col = nombre_y_apellido, 
             c(apellido, nombre), 
             sep = ", ")


knitr::kable(df)
nombre apellido year
Pedro Navaja 1978
Bob Dylan 1941
Peter Pan 1904
knitr::kable(df_2)
nombre_y_apellido year
Navaja, Pedro 1978
Dylan, Bob 1941
Pan, Peter 1904