Transformar amb dplyr

En aquest apartat aprendrem a transformar el marc de dades. Per què volem transformar un marc de dades? Aquestes són les funcions del paquet dplyr que més utilitzarem:

  • Filtrar: Si volem reduir el nombre d’observacions utilitzarem la funció filter().
  • Seleccionar: Si volem reduir el nombre de columnes utilitzarem la funció select().
  • Ordenar: Si volem ordenar les observacions pels valors d’una determinada columna: utilitzarem la funció arrange().
  • Mutar: Si volem crear una nova columna a partir de valors d’altres columnes: utilitzarem la funció mutate().
  • Resumir: Si volem resumir vàries observacions mitjançant una operació: utilitzarem la funció summarize().
  • Agrupar: Si volem canviar la unitat d’anàlisi de les operacions: utilitzarem la funció group_by().

En aquest apartat aplicarem les funcions del paquet dplyr al marc de dades gapminder. Per procedir, haurem de carregar els dos paquets:

#recordeu que els paquets han d'estar prèviament instal·lats 
library(gapminder)
library(dplyr)

L’operador pipe

És imprescindible que sapigueu com funciona el símbol %>%, que en direm l’operador pipe. Fins ara, hem après que les funcions s’apliquen així:

  • El primer argument dins d’una funció acostuma a ser el marc de dades o un objecte. Per exemple:
    • funcio1(marcdades, argument2, argument3 ...)
    • funcio2(marcdades, argument2, argument3 ...)
  • Per tant, si volem aplicar vàries funcions i arguments al mateix marc de dades hauríem de fer quelcom com per exemple:
    • funcio2(funcio1(marcdades, argument2), argument2)
  • Resulta bastant complicat de llegir una funció així.

El que fa la funció pipe és facilitar-nos la lectura del codi, ordenant les funcions de diferent manera. Amb la pipe canviem l’ordre amb què escrivim les funcions, de manera que:

  • Primer indiquem el marc de dades de referència seguit del símbol pipe.
  • A continuació funcio1(argument2, argument3 ...) i també ho acabem amb una pipe.
  • A continuació funcio2(argument2, argument3 ...) i també ho acabem amb una pipe.
  • I així successivament, com es mostra en l’exemple del codi següent:
marcdades %>%
  funcio1(argument2) %>%
  funcio2(argument2, argument3) %>%
  funcio3(argument2)
  ...

Filtrar

Apliquem filter() si volem reduir el nombre d’observacions. Per exemple, si només ens interessa treballar amb un sol país del marc de dades:

 gapminder %>%
 filter(country == "France")
## # A tibble: 12 x 6
##    country continent  year lifeExp      pop gdpPercap
##    <fct>   <fct>     <int>   <dbl>    <int>     <dbl>
##  1 France  Europe     1952    67.4 42459667     7030.
##  2 France  Europe     1957    68.9 44310863     8663.
##  3 France  Europe     1962    70.5 47124000    10560.
##  4 France  Europe     1967    71.6 49569000    13000.
##  5 France  Europe     1972    72.4 51732000    16107.
##  6 France  Europe     1977    73.8 53165019    18293.
##  7 France  Europe     1982    74.9 54433565    20294.
##  8 France  Europe     1987    76.3 55630100    22066.
##  9 France  Europe     1992    77.5 57374179    24704.
## 10 France  Europe     1997    78.6 58623428    25890.
## 11 France  Europe     2002    79.6 59925035    28926.
## 12 France  Europe     2007    80.7 61083916    30470.

És important tenir en compte que el resultat de dins el parèntesi de la funció filter() ha de ser un vector lògic. Podem combinar diferents operacions amb els següents símbols:

  • Amb la coma (,) o el símbol & ens retorna els valors que compleixen tots els requisits.
  • Amb el símbol | ens retorna els valors que compleixen un o l’altre requisit.
  • Amb el símbol %in% ens retorna els valors que indiquem en un vector.
gapminder %>%
 filter(year == 1992, gdpPercap > 30000)

gapminder %>%
 filter(year >= 1992 | gdpPercap > 24000)

gapminder %>%
 filter(year != 1992 & gdpPercap <= 24000)

gapminder %>%
 filter(country %in% c("France", "Germany", "Spain"))
## # A tibble: 4 x 6
##   country       continent  year lifeExp       pop gdpPercap
##   <fct>         <fct>     <int>   <dbl>     <int>     <dbl>
## 1 Kuwait        Asia       1992    75.2   1418095    34933.
## 2 Norway        Europe     1992    77.3   4286357    33966.
## 3 Switzerland   Europe     1992    78.0   6995447    31872.
## 4 United States Americas   1992    76.1 256894189    32004.
## # A tibble: 592 x 6
##    country     continent  year lifeExp      pop gdpPercap
##    <fct>       <fct>     <int>   <dbl>    <int>     <dbl>
##  1 Afghanistan Asia       1992    41.7 16317921      649.
##  2 Afghanistan Asia       1997    41.8 22227415      635.
##  3 Afghanistan Asia       2002    42.1 25268405      727.
##  4 Afghanistan Asia       2007    43.8 31889923      975.
##  5 Albania     Europe     1992    71.6  3326498     2497.
##  6 Albania     Europe     1997    73.0  3428038     3193.
##  7 Albania     Europe     2002    75.7  3508512     4604.
##  8 Albania     Europe     2007    76.4  3600523     5937.
##  9 Algeria     Africa     1992    67.7 26298373     5023.
## 10 Algeria     Africa     1997    69.2 29072015     4797.
## # … with 582 more rows
## # A tibble: 1,468 x 6
##    country     continent  year lifeExp      pop gdpPercap
##    <fct>       <fct>     <int>   <dbl>    <int>     <dbl>
##  1 Afghanistan Asia       1952    28.8  8425333      779.
##  2 Afghanistan Asia       1957    30.3  9240934      821.
##  3 Afghanistan Asia       1962    32.0 10267083      853.
##  4 Afghanistan Asia       1967    34.0 11537966      836.
##  5 Afghanistan Asia       1972    36.1 13079460      740.
##  6 Afghanistan Asia       1977    38.4 14880372      786.
##  7 Afghanistan Asia       1982    39.9 12881816      978.
##  8 Afghanistan Asia       1987    40.8 13867957      852.
##  9 Afghanistan Asia       1997    41.8 22227415      635.
## 10 Afghanistan Asia       2002    42.1 25268405      727.
## # … with 1,458 more rows
## # A tibble: 36 x 6
##    country continent  year lifeExp      pop gdpPercap
##    <fct>   <fct>     <int>   <dbl>    <int>     <dbl>
##  1 France  Europe     1952    67.4 42459667     7030.
##  2 France  Europe     1957    68.9 44310863     8663.
##  3 France  Europe     1962    70.5 47124000    10560.
##  4 France  Europe     1967    71.6 49569000    13000.
##  5 France  Europe     1972    72.4 51732000    16107.
##  6 France  Europe     1977    73.8 53165019    18293.
##  7 France  Europe     1982    74.9 54433565    20294.
##  8 France  Europe     1987    76.3 55630100    22066.
##  9 France  Europe     1992    77.5 57374179    24704.
## 10 France  Europe     1997    78.6 58623428    25890.
## # … with 26 more rows

El següent vídeo us ho explica.

Font: Datacamp

Per treballar amb un marc de dades filtrat sempre és més pràctic guardar-lo com a un nou objecte. En aquest cas hem demanat només els valors del continent africà i ho hem guardat com a objecte gap_afr.

gap_afr <- gapminder %>%
  filter(continent == "Africa")

unique(gap_afr$continent) #fixeu-vos com aquesta variable és un vector
## [1] Africa
## Levels: Africa Americas Asia Europe Oceania
#podem eliminar els nivells amb droplevels() 

Seleccionar

Reduïm el nombre de columnes amb select():

  • Ens retornarà el marc de dades amb l’ordre de les columnes que hem indicat a dins la funció. Les columnes que no indiquem ens les eliminarà.
  • El símbol - ens elimina la columna que indiquem.
  • El símbol : ens retorna de la columna que indiquem a l’esquerra del símbol a la columna que indiquem a la dreta.
  • Podem utilitzar la funció select() simplement per reordenar columnes.
gapminder %>% #seleccionem country, year i pop
 select(country, year, pop)

gapminder %>% #eliminem gdpPercap
 select(-gdpPercap)

gapminder %>% #seleccionem de country fins a year i gdpPercap
 select(country:year, gdpPercap)

gapminder %>% #reordenem les columnes
 select(country, year, continent, lifeExp, gdpPercap, pop)

Ordenar

Ordenem amb arrange() per una o més columnes. Podem introduir més d’una columna. Ens ordenarà primer per la primera columna, després per la segona columna i així successivament.

gapminder %>%
 arrange(continent, lifeExp)

Per defecte ordenem en ordre ascendent. Si volem que ens ordeni en ordre descendent haurem d’introduir desc().

gapminder %>%
 arrange(desc(lifeExp))
## # A tibble: 6 x 6
##   country          continent  year lifeExp       pop gdpPercap
##   <fct>            <fct>     <int>   <dbl>     <int>     <dbl>
## 1 Japan            Asia       2007    82.6 127467972    31656.
## 2 Hong Kong, China Asia       2007    82.2   6980412    39725.
## 3 Japan            Asia       2002    82   127065841    28605.
## 4 Iceland          Europe     2007    81.8    301931    36181.
## 5 Switzerland      Europe     2007    81.7   7554661    37506.
## 6 Hong Kong, China Asia       2002    81.5   6762476    30209.

Mutar

Amb mutate() creem una nova columna a través dels valors d’una altra columna. Funciona de la següent manera:

  • Primer introduïm el nom de la columna de destí, seguit d’un igual i de l’operació que vulguem fer.
  • Si com a columna de destí indiquem el nom d’una columna que ja figura al marc de dades, ens sobreescriurà els resultats (exemple pop).
  • Si com a columna de destí indiquem el nom d’una columna que no figura al marc de dades, ens crearà una nova columna amb el nom de la columna de destí (exemple gdp).
gapminder %>%
 mutate(pop = pop / 1000000) #substitueix la columna pop
gapminder %>%
 mutate(gdp = gdpPercap * pop) %>% #crea la columna gdp perquè no existia prèviament en el marc de dades
 head()
## # A tibble: 6 x 7
##   country     continent  year lifeExp      pop gdpPercap          gdp
##   <fct>       <fct>     <int>   <dbl>    <int>     <dbl>        <dbl>
## 1 Afghanistan Asia       1952    28.8  8425333      779.  6567086330.
## 2 Afghanistan Asia       1957    30.3  9240934      821.  7585448670.
## 3 Afghanistan Asia       1962    32.0 10267083      853.  8758855797.
## 4 Afghanistan Asia       1967    34.0 11537966      836.  9648014150.
## 5 Afghanistan Asia       1972    36.1 13079460      740.  9678553274.
## 6 Afghanistan Asia       1977    38.4 14880372      786. 11697659231.

Amb les funcions que coneixem fins ara podem enllaçar les operacions següents:

gap_asia <- gapminder %>%
  filter(year == 1952, #demanem dades de l'any 1952 i (AND) ...
         continent == "Asia") %>% # ... del continent asiàtic
  select(-continent, -year) %>% #eliminem les columnes continent i any
  mutate(gdp = gdpPercap * pop, #creem la variable gdp
         perc_gdp = gdp / sum(gdp)) %>% #creem la variable perc_gdp
  arrange(desc(gdp)) #ordenem per la columna gdp

Fixeu-vos que sempre podem fer operacions sobre columnes que acabem de crear. En l’exemple hem creat la columna gdp i acte seguit l’hem utilitzat per crear una nova variable.

Resumir

Amb summarize() demanem un resum d’una variable. Per exemple, en la següent funció demanem que ens resumeixi el marc de dades gap_asia de la següent manera:

  • Volem saber quant suma la població.
  • Quina és la mitjana del PIB per càpita.
  • Quina és la proporció de països que tenen un PIB per càpita superior a la mitjana.
  • En quants casos l’esperança de vida és superior a 60.
  • De quin nombre total de casos disposem.
gap_asia %>%
  summarize(tpop = sum(pop),
            mean_gdpcap = mean(gdpPercap, na.rm = TRUE),
            prop = mean(gdpPercap > mean_gdpcap),
            esp = sum(lifeExp > 60),
            count = n())
## # A tibble: 1 x 5
##         tpop mean_gdpcap   prop   esp count
##        <int>       <dbl>  <dbl> <int> <int>
## 1 1395357351       5195. 0.0909     4    33

Agrupar

Amb la funció group_by() agrupem les operacions posteriors a partir d’una variable categòrica. Per exemple, a continuació hem demanat sumaris molt semblants al codi anterior, però agrupats per continent. Ens retornarà un sumari per cada valor de la variable continent, per tant, per cada un dels cinc continents.

gapminder %>%
  filter(year == 1952) %>%
  group_by(continent) %>% #agrupem per una o més variables categòriques
  summarize(tpop = sum(pop),
            mean_gdpcap = mean(gdpPercap, na.rm = TRUE),
            prop = mean(gdpPercap > mean_gdpcap),
            esp = sum(lifeExp > 60),
            count = n())
## # A tibble: 5 x 6
##   continent       tpop mean_gdpcap   prop   esp count
##   <fct>          <int>       <dbl>  <dbl> <int> <int>
## 1 Africa     237640501       1253. 0.327      0    52
## 2 Americas   345152446       4079. 0.24       6    25
## 3 Asia      1395357351       5195. 0.0909     4    33
## 4 Europe     418120846       5661. 0.433     23    30
## 5 Oceania     10686006      10298. 0.5        2     2

Recapitulant dplyr

Aquí podeu veure totes les funcions en un mateix codi:

gapminder %>%
  filter(year == 2002) %>% #filtrem per l'any 2002
  mutate(gdp = gdpPercap * pop) %>% #creem la nova variable gdp
  group_by(continent) %>% #agrupem per continent
  summarize(max_pop = max(pop), #quin és el máxim de població? (a cada continent)
            min_pop = min(pop), #quin és el mínim de població? (a cada continent)
            diff = max_pop - min_pop, #quina és la diferència entre la població màxima i mínima? (a cada continent)
            count = n()) %>% #quantes observacions tenim? (a cada continent)
  arrange(desc(diff)) %>% #ordena per la columna diff en ordre descendent
  select(continent, diff, everything()) #primer vull veure les columnes continent i diff i després la resta 
## # A tibble: 5 x 5
##   continent       diff    max_pop min_pop count
##   <fct>          <int>      <int>   <int> <int>
## 1 Asia      1279743603 1280400000  656397    33
## 2 Americas   286573694  287675526 1101832    25
## 3 Africa     119730902  119901274  170372    52
## 4 Europe      82062641   82350671  288030    30
## 5 Oceania     15638755   19546792 3908037     2

Molt important per al domini de dplyr:

Podeu trobar un resum d’aquest capítol en aquest vídeo:

Font: Datacamp

Referències

Grolemund, Garrett, and Hadley Wickham. 2020. R para Ciencia de Datos. O’Reilly. https://es.r4ds.hadley.nz/index.html.
Previous
Next