library (tidyverse)
## -- Attaching packages --------------------------------------- tidyverse 1.3.1 --
## v ggplot2 3.3.3     v purrr   0.3.4
## v tibble  3.1.2     v dplyr   1.0.6
## v tidyr   1.1.3     v stringr 1.4.0
## v readr   1.4.0     v forcats 0.5.1
## -- Conflicts ------------------------------------------ tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
library(magrittr)
## 
## Attaching package: 'magrittr'
## The following object is masked from 'package:purrr':
## 
##     set_names
## The following object is masked from 'package:tidyr':
## 
##     extract

representar usando las funciones

(((12*5) - 11)/7) + 3
## [1] 10

add() substract() multiply_by() divide_by()

Solución:

add(divide_by(subtract(multiply_by(12, 5), 11), 7), 3)
## [1] 10

Si quisiéramos que cada función ocupe su propia línea, podemos hacerlo de esta manera:

add(
  divide_by(
    subtract(
      multiply_by(12, 
                  5), 
      11), 
    7), 
  3)
## [1] 10

Aunque esto nos permite entender la secuencia de adentro hacia afuera no necesariamente favorece su lectura

Secuencia de objetos intermedios

Esto parece más entendible y al leerlo se sigue la estructura de pasos descritos anteriormente. Vemos que al igual que con las funciones de dplyr, las funciones de magrittr siempre tienen el mismo primer argumento: el objeto a transformar.

numero_inicial <- 12
resultado1 <- multiply_by(numero_inicial, 5)
resultado2 <- subtract(resultado1, 11)
resultado3 <- divide_by(resultado2, 7)
resultado_final <- add(resultado3, 3)
resultado_final
## [1] 10

Si no deseo ir asignando nombres nuevos, puedo ir sobreescribiendo el valor de mi objeto en cada paso. De esta manera se ve más claro que el primer argumento de cada función depende del paso anterior.

numero <- 12
numero <- multiply_by(numero, 5)
numero <- subtract(numero, 11)
numero <- divide_by(numero, 7)
numero <- add(numero, 3)
numero
## [1] 10

Funciones encadenadas con pipe

Si uso pipes (%>%) no necesito crear objetos intermedios y el operador puede leerse como luego. Tomo el 12, luego multiplico por 5, luego resto 11, luego divido entre 7, luego aumento 3.

(((12 * 5) - 11)/ 7) + 3
## [1] 10

Sería:

12 %>% 
  multiply_by(5) %>% 
  subtract(11) %>% 
  divide_by(7) %>% 
  add(3)
## [1] 10

Hemos conseguido el mismo resultado de tres maneras distintas, pero usando pipes hemos encadenado varias funciones una tras otra sin sacrificar la legibilidad de nuestro código ni llenar el Environment de objetos innecesarios.

Atajo de teclado para %>%

Windows ► Ctrl + shift + M
Mac ► Opt + Alt + M

Ejercicio

Representa las siguientes operaciones usando pipes

(((10 + 30) * 3) / 12) - 5
## [1] 5

Solución 1:

10 %>% 
  add(30)%>%
  multiply_by(3)%>%
  divide_by(12) %>%
  subtract(5)
## [1] 5
(((7 - 3) / 2) + 3) * 20
## [1] 100

Solución 2:

7%>% 
  subtract(3)%>% 
  divide_by(2) %>%
  add(3)%>% 
  multiply_by(20)
## [1] 100

Usar pipes con las funciones de dplyr

Una vez entendido el uso de pipes, podemos aplicarlo a nuestro análisis de datos. Seguimos trabajando con gapminder.

library(readxl)

library (dplyr)

 gapminder <- read_xlsx("data/gapminder.xlsx")
gapminder
## # A tibble: 1,704 x 6
##    country     continent  year lifeExp      pop gdpPercap
##    <chr>       <chr>     <dbl>   <dbl>    <dbl>     <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       1992    41.7 16317921      649.
## 10 Afghanistan Asia       1997    41.8 22227415      635.
## # ... with 1,694 more rows

En gapminder tengo todo lo necesario para obtener el ranking del promedio del PBI nacional para cada uno de los cinco continentes en los años 1987 y 2007 (esto me permitirá comparar los cambios en la economía mundial en esos treinta años).

Para ello voy a requerir usar todas las funciones de dplyr que he aprendido hasta el momento. Primero lo haremos paso por paso y luego convertiremos todo en el flujo de unos cuantos pipes.

Como quiero mostrar el resultado de cada paso realizado, rodeo la asignación de mi objeto con paréntesis

Debido a que sólo necesito los años 1987 y 2007, filtro mis datos. Al objeto modificado lo llamaré gapminder_modificado.

(gapminder_modificado <- filter(gapminder, year %in% c(1987, 2007)) )
## # A tibble: 284 x 6
##    country     continent  year lifeExp      pop gdpPercap
##    <chr>       <chr>     <dbl>   <dbl>    <dbl>     <dbl>
##  1 Afghanistan Asia       1987    40.8 13867957      852.
##  2 Afghanistan Asia       2007    43.8 31889923      975.
##  3 Albania     Europe     1987    72    3075321     3739.
##  4 Albania     Europe     2007    76.4  3600523     5937.
##  5 Algeria     Africa     1987    65.8 23254956     5681.
##  6 Algeria     Africa     2007    72.3 33333216     6223.
##  7 Angola      Africa     1987    39.9  7874230     2430.
##  8 Angola      Africa     2007    42.7 12420476     4797.
##  9 Argentina   Americas   1987    70.8 31620918     9140.
## 10 Argentina   Americas   2007    75.3 40301927    12779.
## # ... with 274 more rows

El siguiente paso es quedarme sólo con las variables que necesito. En este caso son continente, año, PBI per cápita y población.

(gapminder_modificado <- select(gapminder_modificado, 
                               continent, year, gdpPercap, pop) )
## # A tibble: 284 x 4
##    continent  year gdpPercap      pop
##    <chr>     <dbl>     <dbl>    <dbl>
##  1 Asia       1987      852. 13867957
##  2 Asia       2007      975. 31889923
##  3 Europe     1987     3739.  3075321
##  4 Europe     2007     5937.  3600523
##  5 Africa     1987     5681. 23254956
##  6 Africa     2007     6223. 33333216
##  7 Africa     1987     2430.  7874230
##  8 Africa     2007     4797. 12420476
##  9 Americas   1987     9140. 31620918
## 10 Americas   2007    12779. 40301927
## # ... with 274 more rows

A continuación, debo obtener el PBI nacional multiplicando el PBI per cápita por la población.

(gapminder_modificado <- mutate(gapminder_modificado,
                               PBI_nacional = pop * gdpPercap) )
## # A tibble: 284 x 5
##    continent  year gdpPercap      pop  PBI_nacional
##    <chr>     <dbl>     <dbl>    <dbl>         <dbl>
##  1 Asia       1987      852. 13867957  11820990309.
##  2 Asia       2007      975. 31889923  31079291949.
##  3 Europe     1987     3739.  3075321  11498418358.
##  4 Europe     2007     5937.  3600523  21376411360.
##  5 Africa     1987     5681. 23254956 132119742845.
##  6 Africa     2007     6223. 33333216 207444851958.
##  7 Africa     1987     2430.  7874230  19136019189.
##  8 Africa     2007     4797. 12420476  59583895818.
##  9 Americas   1987     9140. 31620918 289004799539.
## 10 Americas   2007    12779. 40301927 515033625357.
## # ... with 274 more rows

Ahora que tengo el PBI nacional, puedo obtener el promedio por año y continente.

gapminder_modificado <- group_by(gapminder_modificado, continent, year)
gapminder_modificado <- summarise(gapminder_modificado, promedio = mean(PBI_nacional))
## `summarise()` has grouped output by 'continent'. You can override using the `.groups` argument.
(gapminder_modificado <- ungroup(gapminder_modificado) )
## # A tibble: 10 x 3
##    continent  year      promedio
##    <chr>     <dbl>         <dbl>
##  1 Africa     1987  24107264108.
##  2 Africa     2007  45778570846.
##  3 Americas   1987 439447790357.
##  4 Americas   2007 776723426068.
##  5 Asia       1987 241784763369.
##  6 Asia       2007 627513635079.
##  7 Europe     1987 316507473546.
##  8 Europe     2007 493183311052.
##  9 Oceania    1987 209451563998.
## 10 Oceania    2007 403657044512.

Ahora sólo me falta ordenar mis datos de manera descendente según el promedio del PBI.

(gapminder_modificado <- arrange(gapminder_modificado, year, desc(promedio)) )
## # A tibble: 10 x 3
##    continent  year      promedio
##    <chr>     <dbl>         <dbl>
##  1 Americas   1987 439447790357.
##  2 Europe     1987 316507473546.
##  3 Asia       1987 241784763369.
##  4 Oceania    1987 209451563998.
##  5 Africa     1987  24107264108.
##  6 Americas   2007 776723426068.
##  7 Asia       2007 627513635079.
##  8 Europe     2007 493183311052.
##  9 Oceania    2007 403657044512.
## 10 Africa     2007  45778570846.

Listo. Con el flujo de análisis terminado, puedo verificar que en esos treinta años, Asia superó a Europa en el promedio de su PBI nacional.

Podría juntar todos estos pasos en un solo bloque para que quede claro lo que sucedió.

gapminder_modificado <- filter(gapminder, year %in% c(1987, 2007)) 

gapminder_modificado <- select(gapminder_modificado, continent, year, gdpPercap, pop)

gapminder_modificado <- mutate(gapminder_modificado, PBI_nacional = pop * gdpPercap)

gapminder_modificado <- group_by(gapminder_modificado, continent, year)

gapminder_modificado <- summarise(gapminder_modificado, promedio = mean(PBI_nacional))
## `summarise()` has grouped output by 'continent'. You can override using the `.groups` argument.
gapminder_modificado <- ungroup(gapminder_modificado)

gapminder_modificado <- arrange(gapminder_modificado, year, desc(promedio))

Reescribiendo el flujo con pipes

Podemos hacer todo el análisis usando pipes.

gapminder %>% 
  filter(year %in% c(1987, 2007)) %>%
  select(continent, year, gdpPercap, pop) %>% 
  mutate(PBI_nacional = pop * gdpPercap) %>% 
  group_by(continent, year) %>% 
  summarise(promedio = mean(PBI_nacional)) %>% 
  ungroup() %>% 
  arrange(year, desc(promedio))
## `summarise()` has grouped output by 'continent'. You can override using the `.groups` argument.
## # A tibble: 10 x 3
##    continent  year      promedio
##    <chr>     <dbl>         <dbl>
##  1 Americas   1987 439447790357.
##  2 Europe     1987 316507473546.
##  3 Asia       1987 241784763369.
##  4 Oceania    1987 209451563998.
##  5 Africa     1987  24107264108.
##  6 Americas   2007 776723426068.
##  7 Asia       2007 627513635079.
##  8 Europe     2007 493183311052.
##  9 Oceania    2007 403657044512.
## 10 Africa     2007  45778570846.

Hemos obtenido el mismo resultado escribiendo mucho menos código y sin crear ningún objeto intermedio.

Ejercicio 1

Utilizando gapminder y las funciones de dplyr, obtén el ranking del PBI nacional de Perú, México, Colombia y Chile en los años 1967, 1987 y 2007.

Guíate de esta secuencia:

  1. Usar gapminder
  2. Filtrar los datos de los cuatro países y los años seleccionados
  3. Seleccionar las variables pais, año, población y pbi per cápita
  4. Calcular el pbi total para cada observación
  5. Agrupar las observaciones por año
  6. Organizar por valor de pbi total en orden descendente
  7. Desagrupar las observaciones
gapminder %>%
select (country, year, pop, gdpPercap) %>%
filter (country %in% c("Peru", "Mexico", "Colombia", "Chile"), year %in% c(1967, 1987, 2007)) %>%
mutate(PBI_TOTAL = pop * gdpPercap) %>%
group_by (year) %>%
arrange(year, PBI_TOTAL) %>%
ungroup()
## # A tibble: 12 x 5
##    country   year       pop gdpPercap PBI_TOTAL
##    <chr>    <dbl>     <dbl>     <dbl>     <dbl>
##  1 Chile     1967   8858908     5107.   4.52e10
##  2 Colombia  1967  19764027     2679.   5.29e10
##  3 Peru      1967  12132200     5788.   7.02e10
##  4 Mexico    1967  47995559     5755.   2.76e11
##  5 Chile     1987  12463354     5547.   6.91e10
##  6 Peru      1987  20195924     6361.   1.28e11
##  7 Colombia  1987  30964245     4903.   1.52e11
##  8 Mexico    1987  80122492     8688.   6.96e11
##  9 Peru      2007  28674757     7409.   2.12e11
## 10 Chile     2007  16284741    13172.   2.14e11
## 11 Colombia  2007  44227550     7007.   3.10e11
## 12 Mexico    2007 108700891    11978.   1.30e12

Ejercicio 2

Realiza un análisis que permita responder a la pregunta:

¿Qué continentes tuvieron la mejor y peor expectativa de vida mediana en 1992?

gapminder %>%
filter(year %in% 1992) %>%
select(continent, year, lifeExp, pop) %>%
group_by (continent)%>%
summarise(mediana = median (lifeExp)) %>%
ungroup()%>%
arrange (mediana)
## # A tibble: 5 x 2
##   continent mediana
##   <chr>       <dbl>
## 1 Africa       52.4
## 2 Asia         68.7
## 3 Americas     69.9
## 4 Europe       75.5
## 5 Oceania      76.9

Ejercicio 3

Realiza un análisis que permita responder a la pregunta:

¿Qué continente tuvo el mayor porcentaje de países con expectativa de vida superior a la mediana mundial en 2007?

gapminder %>%
filter (year == 2007) %>%
mutate (mediana_mundial = median(lifeExp),
mayor_que_mediana = lifeExp > mediana_mundial) %>%
group_by(continent) %>%
summarise(n_paises = n(), n_paises_mayor_que_mediana = sum(mayor_que_mediana)) %>%
ungroup() %>%
mutate(porcentaje_paises_mayores =n_paises_mayor_que_mediana/n_paises*100) %>%
arrange(desc(porcentaje_paises_mayores))
## # A tibble: 5 x 4
##   continent n_paises n_paises_mayor_que_mediana porcentaje_paises_mayores
##   <chr>        <int>                      <int>                     <dbl>
## 1 Oceania          2                          2                    100   
## 2 Europe          30                         29                     96.7 
## 3 Americas        25                         17                     68   
## 4 Asia            33                         18                     54.5 
## 5 Africa          52                          5                      9.62