Maneig de dades amb R (I):
the tidyverse way

Mòdul pràctic d’ITA
(Grup M)

Data munging: the tidyverse way



Vam aprendre a carregar dades, però és rar que les dades estiguin preparades per començar la nostra anàlisi, així que cal “arreglar/netejar” les dades. Per això, hem de:

  1. Fer les nostres dades TIDY

  2. Arreglar-los/modificar-los perquè siguin útils per als nostres propòsits

Arreglant les dades

  • Aprendrem a netejar i transformar dades en R. Prioritzarem la nova forma de fer les coses a R (o workflow) conegut com tidyverse.


  • El processat/neteja de les dades sol ocupar un 80% del temps d‟una anàlisi de dades; així que el workflow seria més aviat així:

¿què és el tidyverse?

  • Un conjunt de paquets que treballen en harmonia i que permeten una nova forma d’escriure/programar a R.

principals pkgs del Tidyverse

  • tidyr: convertir a tidy data

  • dplyr: per manipular dades

  • ggplot2: per fer gràfics

  • … i alguns més

ens centrarem principalment en dos paquets: dplyr y ggplot2

“Filosofia” del Tidyverse

Dos principis del tidyverse:

  • Els scripts han de ser “fàcilment” llegibles per les persones

  • Resoldre problemes complexos encadenant funcions simples amb l’operador pipe (%>%)


L’operador %>% és crucial al tidyverse

  • L’operador pipe li devem a Stefan Bache que el va introduir el 2014 en su pkg magrittr
  • The pipe ha tingut tant èxit que el 2021 va aparèixer una nova pipe a R-base: |>

  • Pots llegir sobre ella aquí

The pipe ( %>% )



  • L’operador %>% és crucial al tidyverse. Cal saber fer-lo servir i entendre’l

  • És fàcil. Aviat us sentireu còmodes amb ell

The pipe

  • The pipe és un operador que passa l’element que hi ha a l’esquerra com a argument de la funció que té a la dreta.



Igual us resulta més fàcil entendre-ho amb exemples

  • Les següents 2 expressions fan exactament el mateix:
head(iris, n = 4)         #- forma habitual de trucar/usar la funció head()

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

The pipe (més exemples)

  • Aquestes 3 expressions també són equivalents, fan exactament el mateix:
head(iris, n = 4)         #- forma habitual de trucar/usar la funció head()

iris %>% head(. , n = 4)  #- usant l'operador pipe (amb el punt actuant com placeholder)

iris %>% head(n = 4)      #- usant l'operador pipe (SENSE el punt)

Què fa la següent expressió?

4 %>% head(iris, .)

per què no funciona la següent expressió?

4 %>% head(iris)

Intenta descobrir/entendre que fa la següent expressió:

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

Tidy data



  • Per treballar à la tidyverse és crucial que les dades siguin “tidy”

-El concepte de dades tidy és senzill. Fer les dades tidy no tant però tenim un paquet per fer-ho fàcil: el pkg tidyr

Un aspecte important del tidyverse és fer les dades 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

Sembla fàcil, i ho és: realment és la situació a què estem acostumats, però … … millor desenvolupar-ho amb uns exemples

Tidy data … exemple I

¿Aquestes dades 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 … exemple II

Aquestes dades 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 … exemple III

Aquestes dades 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í, aquestes sí són dades tidy

  • Són més difícils de llegir pels humans, però és que les dades les llegeixen les màquines!!

Les dades tidy solen estar en format llarg o long

Tidy data en format LONG



  • Per treballar à la tidyverse és crucial que les dades siguin “tidy”(en format LONG)

  • És important aprendre a passar de dades WIDE a LONG y viceversa

  • Amb el pkg tidyr és senzill però …

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


Tasca: converteix “df_wide” a format LLARG

Aquí tens un df en format AMPLE, passa-ho a format LLARG

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 format ample:

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

Ho vull en format llarg:

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
  • T’ajudarà a visualitzar df_wide i veure que columnes contenen valors de la mateixa variable

  • Has de fer servir tidyr::pivot_longer() i en el seu primer argument li has de dir que columnes cal convertir a format “llarg”

#- la funció pivot_longer() transforma les dades de format ample(wide) a format llarg(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ó pivot_longer() transforma les dades de format ample(wide) a format llarg(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 amb tidyr::pivot_wider()

Per què voldríem convertir-lo a format AMPLE?

Tasca: converteix “df_long” a format AMPLE

  • df_longestà en format LLARG, passa-ho a format AMPLE

  • Has de distribuir les dades de salari en columnes: una columna per a cada any

Està a format llarg:

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

Ho vull en format ample: (amb una columna per a cada any)

students w_2014 w_2015 w_2016
Pedro 100 500 200
Carla 400 600 250
María 200 700 900
  • Has de fer servir tidyr::pivot_wider()


  • A l’argument values_from li has de dir quina columna vols que els seus valors es distribueixin entre diverses columnes


  • A l’argument names_from li heu de dir quina columna voleu que els seus valors apareguin com els títols de les noves columnes que es crearan
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

Tasca: converteix UNA ALTRA VEGADA “df_long” a format AMPLE

  • df_long està a format LLARG, passa-ho a format AMPLE

  • Has de distribuir les dades de salari en columnes: PERÒ aquesta vegada vull que hi hagi una columna per a cada persona (Pedro, Carla, …)

Està a format llarg:

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

Ho vull en format ample:

(amb una columna per a cada PERSONA)

periodo Pedro Carla María
w_2014 100 400 200
w_2015 500 600 700
w_2016 200 250 900
  • Has de fer servir tidyr::pivot_wider()


  • A l’argument values_from li has de dir quina columna vols que els seus valors es distribueixin entre diverses columnes


  • ATENÇIO!!! A l’argument names_from li heu de dir quina columna voleu que els seus valors apareguin com els títols de les noves columnes que es crearan
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

Dues funcions més de tidyr



  • El paquet tidyr té moltes funcions. Veurem dos: separate() i unite()

les funcions separate() i unite()


  • separate() i unite() ens facilitaran poder separar i unir columnes


  • Per exemple, fixa’t en el següent dataframe: és tidy?
personajes year
Pedro Navaja 1978
Bob Dylan 1941
Peter Pan 1904

Tasca: Utilitzant tidyr::separate()

  • Separa la columna personajes en dues columnes: nombre y apellido
personajes year
Pedro Navaja 1978
Bob Dylan 1941
Peter Pan 1904
  • Heu d’usar tidyr::separate()


  • Hauràs de donar-li els valors de 3 arguments: col, into y sep

    • a l’argument col has de dir quina columna vols separar

    • a into has de dir quins noms vols que tinguin les noves columnes

    • a sep has de dir quin caràcter separa els dos elements

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

Tasca: Utilitzant tidyr::unite()

  • Unir les columnes nombre i apellidoen una sola columna
nombre apellido year
Pedro Navaja 1978
Bob Dylan 1941
Peter Pan 1904
  • Heu d’usar tidyr::unite()


  • Hauràs de donar-li els valors de “3” arguments:

    • a l’argument col has de dir el nom de la nova columna que es crearà

    • després has de dir quines columnes vols unir

    • a sep has de dir quin caràcter separarà els dos elements que unirem

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