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

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

Data munging: the tidyverse way



Aprendimos a cargar datos y a hacerlos TIDY, pero es raro que los datos estén preparados para empezar nuestro análisis, así que hay que “arreglar/limpiar” los datos

vimos ya la la “teoría” del tidyverse

  • El tidyverse es un conjunto de paquetes de R que facilitan la manipulación de datos, su visualización y modelización


  • dplyr es el paquete más importante a la hora de manipular datos.


  • Sus funciones más importantes son: select(), filter(), mutate(), arrange(), rename, summarise() y group_by().


  • Cada función hace “una sola cosa”, así que para realizar transformaciones complejas hay que ir concatenando instrucciones sencillas con el operador pipe (%>%)

Ejemplos


para aprender a manipular datos con dplyr

CONTAR (observaciones)


  • Es importante saber cómo contar las observaciones que tenemos en distintos grupos

  • Por ejemplo, contar cuantas mujeres hay, o cuantas observaciones hay en cada continente, o cuantas empresas en diferentes sectores, …

… vamos a CONTAR

tenemos 3 formas distintas de contar el nº de observaciones (o filas)

1. Usando mutate() con n()

#- fíjate q con mutate() se mantienen todas las filas y todas las columnas
aa <- gapminder %>% mutate(NN = n())  

nrow(aa)  #- se mantienen las 1704 observaciones
[1] 1704

1. mutate() mantiene el nº de filas originales (1704)

bb <- head(aa, n = 3)
gt::gt(bb)
country continent year lifeExp pop gdpPercap NN
Afghanistan Asia 1952 28.801 8425333 779.4453 1704
Afghanistan Asia 1957 30.332 9240934 820.8530 1704
Afghanistan Asia 1962 31.997 10267083 853.1007 1704

2. Usando summarise() con n()

#- fíjate q  summarise() solo devuelve una fila y una columna
aa <- gapminder %>% summarise(NN = n())

2. summarise() devuelve una fila (por grupo)

gt::gt(aa)
NN
1704

3. Usando count()

aa <- gapminder %>% count()

3. count() devuelve una fila (por grupo)

gt::gt(aa)
n
1704

… seguimos CONTANDO

Pero ahora contamos el nº de observaciones de distintos grupos (por ejemplo el nº de observaciones de cada continente)

  • También podríamos usar mutate() pero esta vez solo usaremos summarise() y count()
# fíjate q  summarise() devuelve una fila por cada grupo
# una fila por cada continente
aa <- gapminder %>% 
  group_by(continent) %>% summarise(NN = n())
gt::gt(aa)
continent NN
Africa 624
Americas 300
Asia 396
Europe 360
Oceania 24
aa <- gapminder %>% count(continent)
gt::gt(aa)
continent n
Africa 624
Americas 300
Asia 396
Europe 360
Oceania 24

… aún seguimos CONTANDO

Contamos el nº de observaciones de distintos grupos, pero ahora definidos por dos variables(por ejemplo el nº de observaciones de cada continente y año)

# fíjate q hay 60 grupos (5 continentes x 12 periodos)
# por lo que devuelve 60 filas, una por grupo
aa <- gapminder %>% 
  group_by(continent, year) %>% summarise(NN = n())


aa <- gapminder %>% count(year, continent)
bb <- head(aa, n = 14)
gt::gt(bb)
year continent n
1952 Africa 52
1952 Americas 25
1952 Asia 33
1952 Europe 30
1952 Oceania 2
1957 Africa 52
1957 Americas 25
1957 Asia 33
1957 Europe 30
1957 Oceania 2
1962 Africa 52
1962 Americas 25
1962 Asia 33
1962 Europe 30

observaciones DISTINTAS


  • A veces es importante ver (y contar) las observaciones DISTINTAS que tengamos (en los distintos grupos de nuestros datos)

… ver/obtener observaciones DISTINTAS con distinct()

  • gapminder tiene 1.704 filas: ninguna repetida
# gapminder tiene 1.704 filas: ninguna repetida
aa <- gapminder %>% distinct()
# gapminder no tiene filas repetidas
nrow(aa) == nrow(gapminder)
[1] TRUE


  • En gapminder hay 5 valores distintos para los continentes
# en gapminder hay 5 valores distintos para los continentes
aa <- gapminder %>% distinct(continent)
# efectivamente 5 continentes
nrow(aa)
[1] 5


  • gapminder tiene 60 filas/combinaciones distintas para continente-año (5 x 12 = 60)
# en gapminder hay 5 valores distintos para los continentes
aa <- gapminder %>% distinct(continent, year)
# efectivamente 60:  5 continentes x 12 periodos
nrow(aa)
[1] 60

CONTAR observaciones DISTINTAS con n_distinct()

  • cuantos países (distintos) hay en cada continente?
# nº de países distintos en cada continente
aa <- gapminder %>% 
  group_by(continent) %>% 
  summarise(NN = n_distinct(country))
gt::gt(aa)
continent NN
Africa 52
Americas 25
Asia 33
Europe 30
Oceania 2
  • cuantos países (distintos) hay cada año en cada continente?
# nº de países distintos en cada continente
aa <- gapminder %>% 
  group_by(year, continent) %>% 
  summarise(NN = n_distinct(country)) %>% ungroup()
gt::gt(head(aa, n = 7))
year continent NN
1952 Africa 52
1952 Americas 25
1952 Asia 33
1952 Europe 30
1952 Oceania 2
1957 Africa 52
1957 Americas 25

obtener/calcular estadísticos


  • Ya os explicaran en Estadística y Econometría qué es un estadístico, cuales son los más importantes y cómo se calculan
  • Los estadísticos más sencillos de entender son: el máximo, el mínimo y la media

calculando ESTADISTICOS: máximo, mínimo, media, ……

  • obtener el máximo, mínimo y media de “lifeExp”:
aa <- gapminder %>% 
  summarise(maximo = max(lifeExp, na.rm = TRUE), 
            minimo = min(lifeExp, na.rm = TRUE), 
            media = mean(lifeExp, na.rm = TRUE) )
gt::gt(aa)
maximo minimo media
82.603 23.599 59.47444


calcular ESTADISTICOS (máximo, mínimo y media) por continente


#- calcular estadísticos por continente
aa <- gapminder %>% group_by(continent) %>% 
  summarise(maximo = max(lifeExp, na.rm = TRUE), 
            minimo = min(lifeExp, na.rm = TRUE), 
            media = mean(lifeExp, na.rm = TRUE) )
aa %>% gt::gt()
continent maximo minimo media
Africa 76.442 23.599 48.86533
Americas 80.653 37.579 64.65874
Asia 82.603 28.801 60.06490
Europe 81.757 43.585 71.90369
Oceania 81.235 69.120 74.32621

ESTADISTICOS para Europa año a año ……


#- calcular estadísticos por CONTINENTE Y AÑO
aa <- gapminder %>% 
1  group_by(continent, year) %>%
2  summarise(maximo = max(lifeExp, na.rm = TRUE),
            minimo = min(lifeExp, na.rm = TRUE), 
            mean = mean(lifeExp, na.rm = TRUE) ) %>% 
3  ungroup() %>%
4  filter(continent == "Europe")
1
primero agrupamos por continente y año
2
Calculamos los estadísticos (para las observaciones de cada año y continente)
3
Al usar group_by() es una buena práctica hacer después un ungroup()
4
Seleccionamos solo los datos de Europa
aa %>% gt::gt() %>% gt::fmt_number(3:5, decimals = 2)
continent year maximo minimo mean
Europe 1952 72.67 43.59 64.41
Europe 1957 73.47 48.08 66.70
Europe 1962 73.68 52.10 68.54
Europe 1967 74.16 54.34 69.74
Europe 1972 74.72 57.01 70.78
Europe 1977 76.11 59.51 71.94
Europe 1982 76.99 61.04 72.81
Europe 1987 77.41 63.11 73.64
Europe 1992 78.77 66.15 74.44
Europe 1997 79.39 68.83 75.51
Europe 2002 80.62 70.84 76.70
Europe 2007 81.76 71.78 77.65

Calcular CRECIMIENTOS



  • En Economía interesa mucho saber cuanto crecen las variables, por ejemplo el PIB, o el desempleo , …, o la esperanza de vida

calculando CRECIMIENTOS


  • calcular el crecimiento de la esperanza de vida, de un periodo a otro, en España
aa <- gapminder %>% 
1  select(country, year, lifeExp) %>%
2  group_by(country) %>%
3  arrange(year) %>%
4  mutate(crecimiento =  lifeExp - lag(lifeExp)) %>%
5  mutate(crecimiento2 = lifeExp - lag(lifeExp, default = first(lifeExp))) %>%
6  ungroup() %>%
7  filter(country == "Spain")
1
Selecciono las variables relevantes
2
Agrupamos por país: los cálculos siguientes se harán para cada país
3
Ordenamos por año: el año más antiguo (1952) el primero
4
Calculamos el crecimiento de la esperanza de vida de un año a otro
5
Mejoramos el calculo anterior de “crecimiento”
6
Al usar group_by() es una buena práctica hacer después un ungroup()
7
Seleccionamos solo los datos de España
gt::gt(aa) %>% 
  gt::fmt_number(3:5, decimals = 2)
country year lifeExp crecimiento crecimiento2
Spain 1952 64.94 NA 0.00
Spain 1957 66.66 1.72 1.72
Spain 1962 69.69 3.03 3.03
Spain 1967 71.44 1.75 1.75
Spain 1972 73.06 1.62 1.62
Spain 1977 74.39 1.33 1.33
Spain 1982 76.30 1.91 1.91
Spain 1987 76.90 0.60 0.60
Spain 1992 77.57 0.67 0.67
Spain 1997 78.77 1.20 1.20
Spain 2002 79.78 1.01 1.01
Spain 2007 80.94 1.16 1.16

calculando CRECIMIENTOS ACUMULADOS

  • calcular el crecimiento de la esperanza de vida ACUMULADO en España
aa <- gapminder %>% 
  select(country, year, lifeExp) %>%   
1  group_by(country) %>%
2  arrange(year) %>%
3  mutate(crecimiento =  lifeExp - lag(lifeExp)) %>%
4  mutate(crecimiento2 = lifeExp - lag(lifeExp, default = first(lifeExp))) %>%
5  mutate(crec_acu2 = cumsum(crecimiento2)) %>%
6  mutate(crec_acu3 = lifeExp - first(lifeExp)) %>%
7  ungroup() %>%
  filter(country == "Spain") 
1
Agrupamos por país: los cálculos siguientes se harán para cada país
2
Ordenamos por año: el año más antiguo (1952) el primero
3
Calculamos el crecimiento de la esperanza de vida de un año a otro
4
“Mejoramos” el calculo anterior de “crecimiento”
5
Usamos cumsum() para calcular el crecimiento acumulado
6
Crecimiento acumulado: calculamos el incremento respecto a la 1ª observación
7
Al usar group_by() es una buena práctica hacer después un ungroup()
gt::gt(aa) %>% 
  gt::fmt_number(3:7, decimals = 2)
country year lifeExp crecimiento crecimiento2 crec_acu2 crec_acu3
Spain 1952 64.94 NA 0.00 0.00 0.00
Spain 1957 66.66 1.72 1.72 1.72 1.72
Spain 1962 69.69 3.03 3.03 4.75 4.75
Spain 1967 71.44 1.75 1.75 6.50 6.50
Spain 1972 73.06 1.62 1.62 8.12 8.12
Spain 1977 74.39 1.33 1.33 9.45 9.45
Spain 1982 76.30 1.91 1.91 11.36 11.36
Spain 1987 76.90 0.60 0.60 11.96 11.96
Spain 1992 77.57 0.67 0.67 12.63 12.63
Spain 1997 78.77 1.20 1.20 13.83 13.83
Spain 2002 79.78 1.01 1.01 14.84 14.84
Spain 2007 80.94 1.16 1.16 16.00 16.00

Calcular PORCENTAJES


  • En Economía interesa saber cuantas observaciones hay en cada grupo: eso se hace contando, por ejemplo contar el nº de personas rubias, morenas o pelirrojas, …., o la población en cada país o continente


  • Una vez hemos contado, muchas veces interesa saber el porcentaje que representa cada grupo respecto al total

  • Para calcular esos porcentajes, hay que contar el total y dividirlo por el nº de observaciones en cada grupo

calculando PORCENTAJES (a mano)

  • Por ejemplo, si en una muestra de 100 personas hay 70 personas con el pelo moreno, los morenos son el 70% del total

  • Evidentemente, se calcula dividiendo: 70/100 = 0.7; si lo multiplicamos x100, un 70%


un ejemplo

  • Si en una muestra de 321 personas hubiesen 243 morenos, 89 rubios y el resto pelirrojos ¿qué porcentaje representa cada grupo?

calculando PORCENTAJES (con R à la tidyverse)


  • Calcular el % que representa cada continente en la población mundial:
#- Calcular % de población de cada continente 
aa <- gapminder %>% 
1  group_by(continent, year) %>%
2  summarise(pob_continent = sum(pop, na.rm = TRUE)) %>% ungroup() %>%
3  group_by(year) %>%
4  mutate(pob_mundo = sum(pob_continent),
5         pob_percent = pob_continent/pob_mundo * 100) %>%
  ungroup()
1
Agrupamos por continente y año
2
Calculo la población de cada continente para cada año
3
Vuelvo a agrupar, ahora solo por años
4
Calculo la población mundial para cada año
5
Finalmente calculamos el porcentaje
gt::gt(head(aa, n = 15)) %>% 
  gt::fmt_number(pob_percent, decimals = 2)
continent year pob_continent pob_mundo pob_percent
Africa 1952 237640501 2406957150 9.87
Africa 1957 264837738 2664404580 9.94
Africa 1962 296516865 2899782974 10.23
Africa 1967 335289489 3217478384 10.42
Africa 1972 379879541 3576977158 10.62
Africa 1977 433061021 3930045807 11.02
Africa 1982 499348587 4289436840 11.64
Africa 1987 574834110 4691477418 12.25
Africa 1992 659081517 5110710260 12.90
Africa 1997 743832984 5515204472 13.49
Africa 2002 833723916 5886977579 14.16
Africa 2007 929539692 6251013179 14.87
Americas 1952 345152446 2406957150 14.34
Americas 1957 386953916 2664404580 14.52
Americas 1962 433270254 2899782974 14.94

Extensión: tabla con la importancia (en términos de población) de cada continente en el tiempo


  • Partimos de la tabla anterior en la que hemos calculado el % que representa la población de cada continente sobre la población mundial
#- Calcular % de población de cada continente 
bb <- aa %>% 
  select(continent, year, pob_mundo, pob_percent) %>%
  tidyr::pivot_wider(names_from = continent, 
                     values_from = pob_percent) 
gt::gt(bb) %>% 
  gt::fmt_number(2, sep_mark = ".", decimals = 0) %>% 
  gt::fmt_number(3:7, decimals = 1)
year pob_mundo Africa Americas Asia Europe Oceania
1952 2.406.957.150 9.9 14.3 58.0 17.4 0.4
1957 2.664.404.580 9.9 14.5 58.7 16.4 0.4
1962 2.899.782.974 10.2 14.9 58.5 15.9 0.5
1967 3.217.478.384 10.4 14.9 59.2 15.0 0.5
1972 3.576.977.158 10.6 14.8 60.1 14.0 0.5
1977 3.930.045.807 11.0 14.7 60.7 13.2 0.4
1982 4.289.436.840 11.6 14.7 60.9 12.4 0.4
1987 4.691.477.418 12.3 14.6 61.2 11.6 0.4
1992 5.110.710.260 12.9 14.5 61.3 10.9 0.4
1997 5.515.204.472 13.5 14.4 61.3 10.3 0.4
2002 5.886.977.579 14.2 14.4 61.2 9.8 0.4
2007 6.251.013.179 14.9 14.4 61.0 9.4 0.4

Calcular RANKINGS


  • En Economía interesa saber el ranking que ocupa cada individuo/país/empresa

calculando RANKINGs

  • Calcular el ranking de España en cuanto a Esperanza de vida
aa <- gapminder %>% 
1  select(country, year, lifeExp) %>%
2  group_by(year) %>%
3    mutate(rank_1 = row_number(desc(lifeExp))) %>%
    mutate(rank_2 = min_rank(desc(lifeExp)) ) %>% 
    #- también puedo calcular el ranking a mano
4    arrange(desc(lifeExp)) %>%
    mutate(rank_mio = 1:n())  %>%
  ungroup() 
1
Selecciono las variables relevantes
2
Agrupamos por año ya que queremos calcular el ranking cada año
3
Podemos usar distintos métodos para calcular el ranking, siempre en función del calor de lifeExp de mayor a menor
4
También puedo calcular el ranking “a mano”. Para ello, antes, he de ordenar las observaciones por desc(lifeExp)
aa %>% 
  filter(country == "Spain") %>% 
  gt::gt() %>% 
  gt::fmt_number(3:5, decimals = 0)
country year lifeExp rank_1 rank_2 rank_mio
Spain 2007 81 6 6 6
Spain 2002 80 8 8 8
Spain 1997 79 8 8 8
Spain 1992 78 7 7 7
Spain 1987 77 5 5 5
Spain 1982 76 4 4 4
Spain 1977 74 8 8 8
Spain 1972 73 8 8 8
Spain 1967 71 10 10 10
Spain 1962 70 18 18 18
Spain 1957 67 26 26 26
Spain 1952 65 24 24 24

2 funciones muy útiles: ifelse() y case_when()


  • ifelse(): ejecuta “algo” de manera condicional

  • case_when(): es una generalización de ifelse()


  • Sí, no parece muy sencillo, pero con ejemplos se entiende mucho mejor

ifelse(): ejecuta “algo” de manera condicional

veamos algunos ejemplos

aa <- gapminder %>% 
  select(-pop) %>% 
  mutate(X1 = ifelse(lifeExp > 70, "longevo", "corta_vida")) %>% 
  mutate(X2 = ifelse(gdpPercap > 10000, "rico", "pobre")) %>% 
  mutate(X3 = ifelse(lifeExp > 70 & gdpPercap > 10000, 
                     "longevo y rico", 
                     "corta_vida y/o pobre")) %>% 
  mutate(X4 = ifelse(continent == "Europe", "país europeo", "no europeo")) 


el resultado es:

aa %>% filter(country %in% c("Spain", "Angola")) %>% 
  filter(year %in% c(1952, 2007)) %>% 
  gt::gt() %>% 
  gt::opt_stylize(style = 3) %>% 
  gt::cols_align(align = "center")
country continent year lifeExp gdpPercap X1 X2 X3 X4
Angola Africa 1952 30.015 3520.610 corta_vida pobre corta_vida y/o pobre no europeo
Angola Africa 2007 42.731 4797.231 corta_vida pobre corta_vida y/o pobre no europeo
Spain Europe 1952 64.940 3834.035 corta_vida pobre corta_vida y/o pobre país europeo
Spain Europe 2007 80.941 28821.064 longevo rico longevo y rico país europeo

case_when(): es una generalización de `ifelse()

A ver si entiendes este ejemplo:

aa <- gapminder %>%
  group_by(continent, year)  %>%
  mutate(media_lifeExp = mean(lifeExp)) %>% 
  mutate(media_gdpPercap = mean(gdpPercap)) %>% 
  mutate(GOOD_or_BAD = case_when( 
    lifeExp > mean(lifeExp) & gdpPercap > mean(gdpPercap)  ~ "good",
    lifeExp < mean(lifeExp) & gdpPercap < mean(gdpPercap)  ~ "bad" ,
    lifeExp < mean(lifeExp) | gdpPercap < mean(gdpPercap)  ~ "medium",
    .default = "otros casos"  ) )

El resultado es:

aa %>% ungroup() %>% filter(country == "Spain") %>% select(-pop) %>%
  gt::gt() %>% 
  gt::fmt_number(sep_mark = ".",   dec_mark = ",", decimals = 0) %>% 
  gt::fmt_number(4:7, sep_mark = ".",   dec_mark = ",", decimals = 2) %>% 
  gt::opt_stylize(style = 2) %>% 
  gt::cols_align(align = "center")
country continent year lifeExp gdpPercap media_lifeExp media_gdpPercap GOOD_or_BAD
Spain Europe 1.952 64,94 3.834,03 64,41 5.661,06 medium
Spain Europe 1.957 66,66 4.564,80 66,70 6.963,01 bad
Spain Europe 1.962 69,69 5.693,84 68,54 8.365,49 medium
Spain Europe 1.967 71,44 7.993,51 69,74 10.143,82 medium
Spain Europe 1.972 73,06 10.638,75 70,78 12.479,58 medium
Spain Europe 1.977 74,39 13.236,92 71,94 14.283,98 medium
Spain Europe 1.982 76,30 13.926,17 72,81 15.617,90 medium
Spain Europe 1.987 76,90 15.764,98 73,64 17.214,31 medium
Spain Europe 1.992 77,57 18.603,06 74,44 17.061,57 good
Spain Europe 1.997 78,77 20.445,30 75,51 19.076,78 good
Spain Europe 2.002 79,78 24.835,47 76,70 21.711,73 good
Spain Europe 2.007 80,94 28.821,06 77,65 25.054,48 good