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

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

Data munging: the tidyverse way



Vam aprendre a carregar dades ia fer-les TIDY, però és rar que les dades estiguin preparades per començar la nostra anàlisi, així que cal “arreglar/netejar” les dades

vam veure ja la la “teoria” del tidyverse

  • El tidyverse és un conjunt de paquets de R que faciliten la manipulació de dades, la seva visualització i modelització


  • dplyrés el paquet més important a l’hora de manipular dades.


  • Les seues funcions més importants són: select(), filter(), mutate(), arrange(), rename, summarise() y group_by().


  • Cada funció fa “una sola cosa”, així que per fer transformacions complexes cal anar concatenant instruccions senzilles amb l’operador pipe (%>%)

Exemples


per aprendre a manipular dades amb dplyr

COMPTAR (observacions)


  • És important saber com explicar les observacions que tenim en diferents grups

  • Per exemple, comptar quantes dones hi ha, o quantes observacions hi ha a cada continent, o quantes empreses en diferents sectors, …

… anem a COMPTAR

tenim 3 formes diferents d’explicar el núm. d’observacions (o files)

1. Usant mutate() amb n()

#-fixa't q amb mutate() es mantenen totes les files i totes les columnes
aa <- gapminder %>% mutate(NN = n())  

nrow(aa)  #- es mantenen les 1704 observacions
[1] 1704

1. mutate() manté el nombre de files originals (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. Usant summarise() amb n()

#- fixa't q summarise() només retorna una fila i una columna
aa <- gapminder %>% summarise(NN = n())

2. summarise() torna una fila (per grup)

gt::gt(aa)
NN
1704

3. Usant count()

aa <- gapminder %>% count()

3. count() torna una fila (per grup)

gt::gt(aa)
n
1704

… seguim CONTANT

Però ara comptem el nombre d’observacions de diferents grups (per exemple el nombre d’observacions de cada continent)

  • També podríem utilitzar mutate() però aquesta vegada només farem servir summarise() i count()
# fixa't q summarise() torna una fila per cada grup
# una fila per cada continent
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

… encara seguim CONTANT

Comptem el nº d’observacions de diferents grups, però ara definits per dues variables(per exemple el nº d’observacions de cada continent i any)

# fixa't q hi ha 60 grups (5 continents x 12 períodes)
# pel que torna 60 files, una per grup
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

observacions DIFERENTS


  • De vegades és important veure (i comptar) les observacions DIFERENTS que tinguem (en els diferents grups de les nostres dades))

… veure/obtenir observacions DIFERENTS amb distinct()

  • gapminder té 1.704 files: cap repetida
# gapminder té 1.704 files: cap repetida
aa <- gapminder %>% distinct()
# gapminder no té files repetides
nrow(aa) == nrow(gapminder)
[1] TRUE


  • A gapminder hi ha 5 valors diferents per als continents
# a gapminder hi ha 5 valors diferents per als continents
aa <- gapminder %>% distinct(continent)
# efectivament 5 continents
nrow(aa)
[1] 5


  • gapminder té 60 files/combinacions diferents per a continent-any (5 x 12 = 60)
# a gapminder hi ha 5 valors diferents per als continents
aa <- gapminder %>% distinct(continent, year)
# efectivament 60: 5 continents x 12 períodes
nrow(aa)
[1] 60

COMPTAR observacions DIFERENTS amb n_distinct()

  • quants països (diferents) hi ha a cada continent?
# nº de països diferents a cada continent
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
  • quants països (diferents) hi ha cada any a cada continent?
# nº de països diferents cada any a cada continent
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

obtenir/calcular estadístics


  • Ja us explicaran a Estadística i Econometria què és un estadístic, quins són els més importants i com es calculen
  • Les estadístics més senzills d’entendre són: el màxim, el mínim i la mitja

calculant ESTADISTICS: màxim, mínim, mitjana, ……

  • obtenir el màxim, mínim i mitjana 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 ESTADÍSTICS (màxim, mínim i mitjana) per continent


#- calcular estadístiques per continent
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

ESTADÍSTICS per a Europa any a any ……


#- calcular estadístiques per CONTINENT I ANY
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
primer agrupem per continent i any
2
Calculem les estadístiques (per a les observacions de cada any i continent)
3
En utilitzar group_by() és una bona pràctica fer després un ungroup()
4
Seleccionem només les dades d’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 CREIXEMENTS



  • A Economia interessa molt saber quant creixen les variables, per exemple el PIB, o la desocupació, …, o l’esperança de vida

calculant CREIXEMENTS


  • calcular el creixement de l’esperança de vida, d’un període a l’altre, a Espanya
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
Seleccioneu les variables rellevants
2
Agrupem per país: els càlculs següents es faran per a cada país
3
Ordenem per any: l’any més antic (1952) el primer
4
Calculem el creixement de l´esperança de vida d´un any a un altre
5
Millorem el càlcul anterior de “creixement”
6
En utilitzar group_by() és una bona pràctica fer després un ungroup()
7
Seleccionem només les dades d’Espanya
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

calculant CREIXEMENTS ACUMULATS

  • calcular el creixement de l’esperança de vida ACUMULAT a Espanya
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
Agrupem per país: els càlculs següents es faran per a cada país
2
Ordenem per any: l’any més antic (1952) el primer
3
Calculem el creixement de l´esperança de vida d´un any a un altre
4
“Millorem” el càlcul anterior de “creixement”
5
Fem servir cumsum() per calcular el creixement acumulat
6
Creixement acumulat: calculem l’increment respecte a la 1ª observació
7
En utilitzar group_by() és una bona pràctica fer despré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 PERCENTATGES


  • A Economia interessa saber quantes observacions hi ha a cada grup: això es fa comptant, per exemple contar el nombre de persones rosses, morenes o pèl-roges, …., o la població en cada país o continent


  • Un cop hem explicat, moltes vegades interessa saber el percentatge que representa cada grup respecte al total

  • Per a calcular aquests percentatges, cal comptar el total i dividir-lo pel nombre d’observacions a cada grup

calculant PERCENTATGES (a mà)

  • Per exemple, si en una mostra de 100 persones hi ha 70 persones amb els cabells bruns, els morens són el 70% del total

  • Evidentment, es calcula dividint: 70/100 = 0.7; si ho multipliquem x100, un 70%


un exemple

  • Si en una mostra de 321 persones hi haguessin 243 morenos, 89 rossos i la resta pèl-rojos, quin percentatge representa cada grup?

calculant PERCENTATGES (amb R à la tidyverse)


  • Calcular el % que representa cada continent a la població mundial:
#- Calcular % de població de cada continent 
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
Agrupem per continent i any
2
Càlcul la població de cada continent per a cada any
3
Torno a agrupar, ara només per anys
4
Càlcul la població mundial per a cada any
5
Finalment calculem el percentatge
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ó: taula amb la importància (en termes de població) de cada continent en el temps


  • Partim de la taula anterior en què hem calculat el % que representa la població de cada continent sobre la població mundial
#- Calcular % de població de cada continent 
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


  • A Economia interessa saber el rànquing que ocupa cada individu/país/empresa

calculant RANKINGs

  • Calcular el rànquing d’Espanya quant a Esperança 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
Seleccione les variables rellevants
2
Agrupem per any ja que volem calcular el rànquing cada any
3
Podem fer servir diferents mètodes per calcular el rànquing, sempre en funció de la calor de lifeExp de major a menor
4
També puc calcular el rànquing “a mà”. Per això, abans, he d’ordenar les observacions per 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 funcions molt útils: ifelse() i case_when()


  • ifelse(): executa “alguna cosa” de manera condicional

  • case_when(): és una generalització de ifelse()


  • Sí, no sembla gaire senzill, però amb exemples s’entén molt millor

ifelse(): executa “alguna cosa” de manera condicional

vegem-ne alguns exemples

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 resultat és:

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(): és una generalització de `ifelse()

A veure si entens aquest exemple:

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 resultat és:

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