8  dplyr - gramática para manipulación de datos

Trabajo previo

Lecturas

Wickham, H., Çetinkaya-Rundel, M., & Grolemund, G. (s. f.). R for Data Science (2nd ed.) Chapter 4 - Data transformation. Recuperado 5 de mayo de 2024, de https://r4ds.hadley.nz/data-transform.html

Introducción

El paquete dplyr de Tidyverse es descrito como una gramática para la manipulación de datos, la cual proporciona un conjunto consistente de “verbos” que ayuda a solucionar los retos de procesamiento de datos más comunes. Los principales verbos (i.e. funciones) de esta gramática son:

select(): selecciona columnas con base en sus nombres.

filter(): selecciona filas con base en sus valores.

arrange(): cambia el orden de las filas.

mutate(): crea nuevas columnas, las cuales se expresan como funciones de columnas existentes.

summarize(): agrupa y resume valores.

Todas estas operaciones pueden combinarse con la función group_by(), la cual ejecuta cualquiera de las operaciones anteriores “en grupo”. Además, dplyr proporciona funciones adicionales para tareas más específicas.

Las funciones de dplyr pueden encadenarse a través del operador pipe (tubo), ya sea el del paquete magrittr (%>%) o el del paquete base de R (|>). En el material de este curso, se prefiere la segunda opción. Los pipes se utilizan para comunicar procesos y así formar pipelines (tuberías).

Todas las funciones de dplyr trabajan de manera similar:

  1. El primer argumento siempre es un data frame. Puede omitirse si la función recibe el data frame a través del operador pipe.
  2. Los argumentos siguientes describen que hacer con el data frame, utilizando los nombres de las columnas (sin comillas).
  3. El resultado siempre es un nuevo data frame.

Ya que cada función de dplyr se especializa en una sola tarea, usualmente es necesario encadenar funciones mediante pipes para lograr un objetivo de procesamiento de datos. Por ejemplo, el siguiente bloque de código usa tres verbos, o funciones, de dplyr para obtener la masa promedio de cada especie de pingüinos que habita en la isla Biscoe.

# Cálculo de la masa promedio para cada especie de pingüinos
# que habita en la isla Biscoe
penguins |>
  filter(island == "Biscoe") |> 
  group_by(species) |> 
  summarize(
    body_mass_g_mean = mean(body_mass_g, na.rm = TRUE)
  )
A tibble: 2 × 2
species body_mass_g_mean
<fct>              <dbl>
Adelie          3710.659
Gentoo          5076.016

8.1 Instalación y carga

El paquete dplyr puede instalarse junto con todos los demás paquete de Tidyverse o de manera individual:

# Instalación conjunta de Tidyverse
install.packages("tidyverse")

# Instalación individual
install.packages("dplyr")

Una vez instalado, dplyr puede cargarse con la función library():

# Carga conjunta de Tidyverse
library(tidyverse)

# Carga individual
library(dplyr)

Seguidamente, se cargan algunos paquetes adicionales que se utilizan en este capítulo.

# Carga de readr, paquete para lectura de datos
library(readr)

# Carga de tidyr, paquete para creación de datos "tidy"
library(tidyr)

# Carga de knitr, paquete para integrar salidas en R en documentos dinámicos
# (ej. Quarto). En este capítulo se usa para generar tablas.
library(knitr)

8.2 Conjuntos de datos para ejemplos

En los ejemplos de este capítulo, se utilizan dos conjunto de datos:

8.2.1 Pingüinos del archipiélago Palmer

Para cargar el conjunto de datos penguins, basta con cargar el paquete palmerpenguins.

# Carga del paquete de datos palmerpenguins
library(palmerpenguins)

La función glimpse() despliega la estructura de un conjunto de datos, incluyendo los nombres de las columnas, sus tipos de datos y una muestra de estos:

# Estructura del conjunto de datos penguins
glimpse(penguins)
Rows: 344
Columns: 8
$ species           <fct> Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Adel…
$ island            <fct> Torgersen, Torgersen, Torgersen, Torgersen, Torgerse…
$ bill_length_mm    <dbl> 39.1, 39.5, 40.3, NA, 36.7, 39.3, 38.9, 39.2, 34.1, …
$ bill_depth_mm     <dbl> 18.7, 17.4, 18.0, NA, 19.3, 20.6, 17.8, 19.6, 18.1, …
$ flipper_length_mm <int> 181, 186, 195, NA, 193, 190, 181, 195, 193, 190, 186…
$ body_mass_g       <int> 3750, 3800, 3250, NA, 3450, 3650, 3625, 4675, 3475, …
$ sex               <fct> male, female, female, NA, female, male, female, male…
$ year              <int> 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007…

La función también puede llamarse mediante un pipe:

# Estructura del conjunto de datos penguins
penguins |>
  glimpse()
Rows: 344
Columns: 8
$ species           <fct> Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Adel…
$ island            <fct> Torgersen, Torgersen, Torgersen, Torgersen, Torgerse…
$ bill_length_mm    <dbl> 39.1, 39.5, 40.3, NA, 36.7, 39.3, 38.9, 39.2, 34.1, …
$ bill_depth_mm     <dbl> 18.7, 17.4, 18.0, NA, 19.3, 20.6, 17.8, 19.6, 18.1, …
$ flipper_length_mm <int> 181, 186, 195, NA, 193, 190, 181, 195, 193, 190, 186…
$ body_mass_g       <int> 3750, 3800, 3250, NA, 3450, 3650, 3625, 4675, 3475, …
$ sex               <fct> male, female, female, NA, female, male, female, male…
$ year              <int> 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007…

Un conjunto de datos puede visualizarse al escribir su nombre en la consola de R o en un programa:

# Despliegue de los datos de penguins
penguins
# A tibble: 344 × 8
   species island    bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
   <fct>   <fct>              <dbl>         <dbl>             <int>       <int>
 1 Adelie  Torgersen           39.1          18.7               181        3750
 2 Adelie  Torgersen           39.5          17.4               186        3800
 3 Adelie  Torgersen           40.3          18                 195        3250
 4 Adelie  Torgersen           NA            NA                  NA          NA
 5 Adelie  Torgersen           36.7          19.3               193        3450
 6 Adelie  Torgersen           39.3          20.6               190        3650
 7 Adelie  Torgersen           38.9          17.8               181        3625
 8 Adelie  Torgersen           39.2          19.6               195        4675
 9 Adelie  Torgersen           34.1          18.1               193        3475
10 Adelie  Torgersen           42            20.2               190        4250
# ℹ 334 more rows
# ℹ 2 more variables: sex <fct>, year <int>

penguins es un tibble, un tipo especial de data frame que se utiliza en Tidyverse. La diferencia más importante entre un tibble y un data frame es la manera en la que se imprimen: los tibbles están diseñados para conjuntos de datos grandes, por lo que solo muestran los primeros registros y las columnas que caben en la pantalla. Un data frame regular muestra todas sus columnas y muchos más registros, lo que dificulta su visualización. Note la diferencia, por ejemplo, con la forma en la que se despliega el conjunto de datos iris (observe también la diferencia entre las salidas de class(iris) y class(penguins)). A pesar de estas diferencias en el despliegue, en general, un data frame regular y un tibble pueden tratarse indistintamente.

Para generar una salida más estilizada, puede usarse la función knitr::kable(), la cual genera tablas para documentos web. En el siguiente ejemplo, se obtienen los primeros registros de penguins con la función head() y se despliegan en una tabla mediante kable().

# Despliegue de los primeros registros de penguins en una tabla kable
penguins |>
  head(n = 10) |>
  kable(format = "html")
species island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g sex year
Adelie Torgersen 39.1 18.7 181 3750 male 2007
Adelie Torgersen 39.5 17.4 186 3800 female 2007
Adelie Torgersen 40.3 18.0 195 3250 female 2007
Adelie Torgersen NA NA NA NA NA 2007
Adelie Torgersen 36.7 19.3 193 3450 female 2007
Adelie Torgersen 39.3 20.6 190 3650 male 2007
Adelie Torgersen 38.9 17.8 181 3625 female 2007
Adelie Torgersen 39.2 19.6 195 4675 male 2007
Adelie Torgersen 34.1 18.1 193 3475 NA 2007
Adelie Torgersen 42.0 20.2 190 4250 NA 2007

8.2.2 Países

Se utiliza la función readr::read_csv() para leer un archivo CSV almacenado en el repositorio GitHub de este curso, con los datos de las estadísticas policiales proporcionados por el OIJ en formato Excel. readr::read_csv() es más eficiente que read.csv() (del paquete base de R) y tiene otras ventajas como detección automática de tipos de datos y mejor integración con otros paquetes de Tidyverse (ej. dplyr, tidyr, ggplot2).

# Carga de los datos de países
paises <-
  read_csv(
    "https://raw.githubusercontent.com/pf0953-programacionr/2024-ii/refs/heads/main/datos/natural-earth/paises.csv"
  )

Estructura del conjunto de datos:

# Estructura de los datos de países
glimpse(paises)
Rows: 201
Columns: 10
$ ADM0_ISO   <chr> "IDN", "MYS", "CHL", "BOL", "PER", "ARG", "GBR", "CYP", "IN…
$ NAME       <chr> "Indonesia", "Malaysia", "Chile", "Bolivia", "Peru", "Argen…
$ CONTINENT  <chr> "Asia", "Asia", "South America", "South America", "South Am…
$ REGION_UN  <chr> "Asia", "Asia", "Americas", "Americas", "Americas", "Americ…
$ SUBREGION  <chr> "South-Eastern Asia", "South-Eastern Asia", "South America"…
$ REGION_WB  <chr> "East Asia & Pacific", "East Asia & Pacific", "Latin Americ…
$ ECONOMY    <chr> "4. Emerging region: MIKT", "6. Developing region", "5. Eme…
$ INCOME_GRP <chr> "4. Lower middle income", "3. Upper middle income", "3. Upp…
$ POP_EST    <dbl> 270625568, 31949777, 18952038, 11513100, 32510453, 44938712…
$ GDP_MD     <dbl> 1119190, 364681, 282318, 40895, 226848, 445445, 2863166, 24…

Despliegue de los datos (debido a que paises es un data frame, pero no un tibble, se limitan manualmente las filas y columnas que se muestran):

# Despliegue de los primeros registros de paises en una tabla kable
paises |>
  head(n = 10) |>
  kable(format = "html")
ADM0_ISO NAME CONTINENT REGION_UN SUBREGION REGION_WB ECONOMY INCOME_GRP POP_EST GDP_MD
IDN Indonesia Asia Asia South-Eastern Asia East Asia & Pacific 4. Emerging region: MIKT 4. Lower middle income 270625568 1119190
MYS Malaysia Asia Asia South-Eastern Asia East Asia & Pacific 6. Developing region 3. Upper middle income 31949777 364681
CHL Chile South America Americas South America Latin America & Caribbean 5. Emerging region: G20 3. Upper middle income 18952038 282318
BOL Bolivia South America Americas South America Latin America & Caribbean 5. Emerging region: G20 4. Lower middle income 11513100 40895
PER Peru South America Americas South America Latin America & Caribbean 5. Emerging region: G20 3. Upper middle income 32510453 226848
ARG Argentina South America Americas South America Latin America & Caribbean 5. Emerging region: G20 3. Upper middle income 44938712 445445
GBR United Kingdom Europe Europe Northern Europe Europe & Central Asia 1. Developed region: G7 1. High income: OECD 67366465 2863166
CYP Cyprus Asia Asia Western Asia Europe & Central Asia 6. Developing region 2. High income: nonOECD 1198575 24948
IND India Asia Asia Southern Asia South Asia 3. Emerging region: BRIC 4. Lower middle income 1366417754 2868929
CHN China Asia Asia Eastern Asia East Asia & Pacific 3. Emerging region: BRIC 3. Upper middle income 1405862845 14762473

8.2.3 Esperanza de vida al nacer

# Carga de los datos de esperanza de vida en países
esperanza_vida <-
  read_csv(
    "https://raw.githubusercontent.com/pf0953-programacionr/2024-ii/refs/heads/main/datos/world-bank/paises-esperanza-vida.csv"
  )

Estructura del conjunto de datos:

# Estructura de los datos de esperanza de vida
glimpse(esperanza_vida)
Rows: 266
Columns: 69
$ `Country Name`   <chr> "Aruba", "Africa Eastern and Southern", "Afghanistan"…
$ `Country Code`   <chr> "ABW", "AFE", "AFG", "AFW", "AGO", "ALB", "AND", "ARB…
$ `Indicator Name` <chr> "Life expectancy at birth, total (years)", "Life expe…
$ `Indicator Code` <chr> "SP.DYN.LE00.IN", "SP.DYN.LE00.IN", "SP.DYN.LE00.IN",…
$ `1960`           <dbl> 64.15200, 44.08555, 32.53500, 37.84515, 38.21100, 54.…
$ `1961`           <dbl> 64.53700, 44.38670, 33.06800, 38.16495, 37.26700, 55.…
$ `1962`           <dbl> 64.75200, 44.75218, 33.54700, 38.73510, 37.53900, 56.…
$ `1963`           <dbl> 65.13200, 44.91316, 34.01600, 39.06372, 37.82400, 57.…
$ `1964`           <dbl> 65.29400, 45.47904, 34.49400, 39.33536, 38.13100, 58.…
$ `1965`           <dbl> 65.50200, 45.49834, 34.95300, 39.61804, 38.49500, 60.…
$ `1966`           <dbl> 66.06300, 45.24910, 35.45300, 39.83783, 38.75700, 60.…
$ `1967`           <dbl> 66.43900, 45.92491, 35.92400, 39.47150, 39.09200, 61.…
$ `1968`           <dbl> 66.75700, 46.22310, 36.41800, 40.08568, 39.48400, 62.…
$ `1969`           <dbl> 67.16800, 46.43230, 36.91000, 40.35042, 39.82900, 63.…
$ `1970`           <dbl> 67.58300, 46.71848, 37.41800, 41.03476, 40.19000, 64.…
$ `1971`           <dbl> 67.97500, 47.19294, 37.92300, 41.55672, 40.55400, 65.…
$ `1972`           <dbl> 68.57700, 46.89739, 38.44400, 42.24979, 40.90500, 66.…
$ `1973`           <dbl> 69.09200, 47.69232, 39.00300, 42.85505, 41.27000, 67.…
$ `1974`           <dbl> 69.50300, 47.59806, 39.55000, 43.49768, 41.65200, 67.…
$ `1975`           <dbl> 69.76200, 47.75989, 40.10000, 44.20125, 41.19100, 68.…
$ `1976`           <dbl> 70.03500, 48.34959, 40.64500, 45.00316, 41.16300, 68.…
$ `1977`           <dbl> 70.26400, 48.63591, 41.22800, 45.71989, 41.43700, 69.…
$ `1978`           <dbl> 70.49400, 48.76360, 40.27100, 46.26954, 41.83000, 69.…
$ `1979`           <dbl> 70.77800, 49.26134, 39.08600, 46.67374, 42.17500, 69.…
$ `1980`           <dbl> 71.06600, 49.63654, 39.61800, 47.01524, 42.44900, 70.…
$ `1981`           <dbl> 71.72200, 50.05707, 40.16400, 47.29719, 42.77200, 70.…
$ `1982`           <dbl> 71.95900, 50.29685, 37.76600, 47.52938, 43.05100, 71.…
$ `1983`           <dbl> 72.10500, 48.70333, 38.18700, 47.78526, 42.09200, 71.…
$ `1984`           <dbl> 72.25100, 48.65266, 33.32900, 47.93192, 42.35300, 71.…
$ `1985`           <dbl> 72.38800, 49.01163, 33.55000, 48.02168, 42.64800, 71.…
$ `1986`           <dbl> 72.46200, 49.63972, 39.39600, 48.06676, 42.84300, 71.…
$ `1987`           <dbl> 72.78900, 50.07589, 39.84400, 48.23785, 40.91700, 72.…
$ `1988`           <dbl> 73.04700, 49.35973, 43.95800, 48.51291, 41.54500, 72.…
$ `1989`           <dbl> 73.02300, 50.68410, 45.15800, 48.68985, 41.76500, 72.…
$ `1990`           <dbl> 73.07600, 50.60773, 45.96700, 48.65000, 41.89300, 73.…
$ `1991`           <dbl> 73.10000, 50.39046, 46.66300, 48.66246, 43.81300, 73.…
$ `1992`           <dbl> 73.17900, 49.96211, 47.59600, 48.73727, 42.20900, 73.…
$ `1993`           <dbl> 73.22500, 50.27363, 51.46600, 48.83204, 42.10100, 73.…
$ `1994`           <dbl> 73.27200, 50.88258, 51.49500, 48.68189, 43.42200, 74.…
$ `1995`           <dbl> 73.34900, 51.00193, 52.54400, 48.78377, 45.84900, 74.…
$ `1996`           <dbl> 73.44800, 50.81069, 53.24300, 48.90628, 46.03300, 74.…
$ `1997`           <dbl> 73.45200, 50.97423, 53.63400, 49.07918, 46.30600, 73.…
$ `1998`           <dbl> 73.49100, 50.32591, 52.94300, 49.33295, 45.05700, 74.…
$ `1999`           <dbl> 73.56100, 51.23785, 54.84600, 49.75012, 45.38600, 75.…
$ `2000`           <dbl> 73.56900, 51.96448, 55.29800, 50.22195, 46.02400, 75.…
$ `2001`           <dbl> 73.64700, 52.18965, 55.79800, 50.56514, 46.59000, 75.…
$ `2002`           <dbl> 73.72600, 52.54079, 56.45400, 50.92785, 47.38600, 75.…
$ `2003`           <dbl> 73.75200, 53.02203, 57.34400, 51.40336, 49.61700, 76.…
$ `2004`           <dbl> 73.57600, 53.54546, 57.94400, 51.81913, 50.59200, 76.…
$ `2005`           <dbl> 73.81100, 54.21965, 58.36100, 52.34455, 51.57000, 76.…
$ `2006`           <dbl> 74.02600, 55.15055, 58.68400, 52.83213, 52.36900, 76.…
$ `2007`           <dbl> 74.21000, 55.93380, 59.11100, 53.25171, 53.64200, 77.…
$ `2008`           <dbl> 74.14700, 56.68042, 59.85200, 53.64116, 54.63300, 77.…
$ `2009`           <dbl> 74.56000, 57.62085, 60.36400, 54.15942, 55.75200, 77.…
$ `2010`           <dbl> 75.40400, 58.41115, 60.85100, 54.55017, 56.72600, 77.…
$ `2011`           <dbl> 75.46500, 59.29327, 61.41900, 55.01314, 57.59600, 78.…
$ `2012`           <dbl> 75.53100, 60.05078, 61.92300, 55.34056, 58.62300, 78.…
$ `2013`           <dbl> 75.63600, 60.70987, 62.41700, 55.67341, 59.30700, 78.…
$ `2014`           <dbl> 75.60100, 61.33792, 62.54500, 55.92223, 60.04000, 78.…
$ `2015`           <dbl> 75.68300, 61.85646, 62.65900, 56.19587, 60.65500, 78.…
$ `2016`           <dbl> 75.61700, 62.44405, 63.13600, 56.58168, 61.09200, 78.…
$ `2017`           <dbl> 75.90300, 62.92239, 63.01600, 56.88845, 61.68000, 79.…
$ `2018`           <dbl> 76.07200, 63.36586, 63.08100, 57.18914, 62.14400, 79.…
$ `2019`           <dbl> 76.24800, 63.75568, 63.56500, 57.55580, 62.44800, 79.…
$ `2020`           <dbl> 75.72300, 63.31386, 62.57500, 57.22637, 62.26100, 76.…
$ `2021`           <dbl> 74.62600, 62.45459, 61.98200, 56.98866, 61.64300, 76.…
$ `2022`           <dbl> 74.99200, 62.89903, 62.87900, 57.62618, 61.92900, 76.…
$ `2023`           <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ ...69            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…

Despliegue de los datos:

# Despliegue de los primeros registros de esperanza de vida en una tabla kable
esperanza_vida |>
  head(n = 10) |>
  kable(format = "html")
Country Name Country Code Indicator Name Indicator Code 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 ...69
Aruba ABW Life expectancy at birth, total (years) SP.DYN.LE00.IN 64.15200 64.53700 64.75200 65.13200 65.29400 65.50200 66.06300 66.43900 66.75700 67.16800 67.58300 67.97500 68.57700 69.09200 69.50300 69.76200 70.03500 70.26400 70.49400 70.77800 71.06600 71.72200 71.95900 72.10500 72.25100 72.38800 72.46200 72.78900 73.04700 73.02300 73.07600 73.10000 73.17900 73.22500 73.27200 73.34900 73.44800 73.45200 73.49100 73.56100 73.56900 73.64700 73.72600 73.75200 73.57600 73.81100 74.02600 74.21000 74.14700 74.56000 75.40400 75.46500 75.53100 75.63600 75.60100 75.68300 75.61700 75.90300 76.07200 76.24800 75.72300 74.62600 74.99200 NA NA
Africa Eastern and Southern AFE Life expectancy at birth, total (years) SP.DYN.LE00.IN 44.08555 44.38670 44.75218 44.91316 45.47904 45.49834 45.24910 45.92491 46.22310 46.43230 46.71848 47.19294 46.89739 47.69232 47.59806 47.75989 48.34959 48.63591 48.76360 49.26134 49.63654 50.05707 50.29685 48.70333 48.65266 49.01163 49.63972 50.07589 49.35973 50.68410 50.60773 50.39046 49.96211 50.27363 50.88258 51.00193 50.81069 50.97423 50.32591 51.23785 51.96448 52.18965 52.54079 53.02203 53.54546 54.21965 55.15055 55.93380 56.68042 57.62085 58.41115 59.29327 60.05078 60.70987 61.33792 61.85646 62.44405 62.92239 63.36586 63.75568 63.31386 62.45459 62.89903 NA NA
Afghanistan AFG Life expectancy at birth, total (years) SP.DYN.LE00.IN 32.53500 33.06800 33.54700 34.01600 34.49400 34.95300 35.45300 35.92400 36.41800 36.91000 37.41800 37.92300 38.44400 39.00300 39.55000 40.10000 40.64500 41.22800 40.27100 39.08600 39.61800 40.16400 37.76600 38.18700 33.32900 33.55000 39.39600 39.84400 43.95800 45.15800 45.96700 46.66300 47.59600 51.46600 51.49500 52.54400 53.24300 53.63400 52.94300 54.84600 55.29800 55.79800 56.45400 57.34400 57.94400 58.36100 58.68400 59.11100 59.85200 60.36400 60.85100 61.41900 61.92300 62.41700 62.54500 62.65900 63.13600 63.01600 63.08100 63.56500 62.57500 61.98200 62.87900 NA NA
Africa Western and Central AFW Life expectancy at birth, total (years) SP.DYN.LE00.IN 37.84515 38.16495 38.73510 39.06372 39.33536 39.61804 39.83783 39.47150 40.08568 40.35042 41.03476 41.55672 42.24979 42.85505 43.49768 44.20125 45.00316 45.71989 46.26954 46.67374 47.01524 47.29719 47.52938 47.78526 47.93192 48.02168 48.06676 48.23785 48.51291 48.68985 48.65000 48.66246 48.73727 48.83204 48.68189 48.78377 48.90628 49.07918 49.33295 49.75012 50.22195 50.56514 50.92785 51.40336 51.81913 52.34455 52.83213 53.25171 53.64116 54.15942 54.55017 55.01314 55.34056 55.67341 55.92223 56.19587 56.58168 56.88845 57.18914 57.55580 57.22637 56.98866 57.62618 NA NA
Angola AGO Life expectancy at birth, total (years) SP.DYN.LE00.IN 38.21100 37.26700 37.53900 37.82400 38.13100 38.49500 38.75700 39.09200 39.48400 39.82900 40.19000 40.55400 40.90500 41.27000 41.65200 41.19100 41.16300 41.43700 41.83000 42.17500 42.44900 42.77200 43.05100 42.09200 42.35300 42.64800 42.84300 40.91700 41.54500 41.76500 41.89300 43.81300 42.20900 42.10100 43.42200 45.84900 46.03300 46.30600 45.05700 45.38600 46.02400 46.59000 47.38600 49.61700 50.59200 51.57000 52.36900 53.64200 54.63300 55.75200 56.72600 57.59600 58.62300 59.30700 60.04000 60.65500 61.09200 61.68000 62.14400 62.44800 62.26100 61.64300 61.92900 NA NA
Albania ALB Life expectancy at birth, total (years) SP.DYN.LE00.IN 54.43900 55.63400 56.67100 57.84400 58.98300 60.01900 60.99800 61.97200 62.94600 63.92300 64.82400 65.61800 66.42200 67.14000 67.76900 68.32800 68.70400 69.12100 69.30900 69.58400 70.47800 70.73000 71.02300 71.29600 71.50200 71.65600 71.95000 72.35200 72.64100 72.88000 73.14400 73.37800 73.71500 73.93900 74.13100 74.36200 74.59200 73.90400 74.99000 75.18300 75.40400 75.63900 75.89000 76.14200 76.37600 76.62100 76.81600 77.54900 77.65300 77.78100 77.93600 78.09200 78.06400 78.12300 78.40700 78.64400 78.86000 79.04700 79.18400 79.28200 76.98900 76.46300 76.83300 NA NA
Andorra AND Life expectancy at birth, total (years) SP.DYN.LE00.IN NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
Arab World ARB Life expectancy at birth, total (years) SP.DYN.LE00.IN 44.97290 45.67640 46.12258 46.97247 47.89576 48.23211 48.45707 48.91291 49.44512 49.82224 50.35134 51.29642 51.86446 52.53968 53.19444 53.70986 54.04753 55.36147 56.11217 56.82629 57.30237 57.69293 58.05480 58.78737 59.47898 60.21574 61.22126 61.16971 60.60903 62.48114 62.92797 63.17961 63.47441 64.45832 65.49673 65.34978 65.71840 65.99442 65.80771 66.87673 67.29733 67.63168 67.93557 67.85900 67.89591 68.16268 68.56725 68.92868 69.28643 69.81264 70.04125 70.26152 70.18046 70.19651 70.49263 70.75822 70.94306 71.42960 71.63302 71.84463 70.92336 70.81448 71.22727 NA NA
United Arab Emirates ARE Life expectancy at birth, total (years) SP.DYN.LE00.IN 48.81100 49.69500 50.68600 51.58400 52.84800 53.98500 55.18500 56.33900 57.54000 58.76000 60.02100 61.21100 62.30400 63.35100 64.33800 65.08000 65.82000 66.51400 67.20900 67.84600 68.53000 69.08500 69.66000 69.94900 70.48500 70.74700 70.96400 71.49100 71.60600 71.75700 71.90000 72.24100 72.30600 72.52100 72.59800 72.69500 72.76700 72.93700 73.06600 73.67000 74.38000 74.63600 74.90100 76.22200 76.45300 76.68300 76.90900 77.12900 77.48800 78.00300 78.33400 78.51700 78.71600 78.85300 79.04400 79.22300 79.33500 79.50400 79.62700 79.72600 78.94600 78.71000 79.19600 NA NA
Argentina ARG Life expectancy at birth, total (years) SP.DYN.LE00.IN 63.97800 64.36000 64.24400 64.44900 64.36300 64.59300 64.89100 64.99200 64.89000 64.85900 65.58900 65.54100 65.92300 66.32300 66.56300 67.08100 67.22800 67.86100 68.19700 68.49100 68.56400 68.97600 68.93700 69.26700 69.19500 69.65100 70.11900 70.56400 71.05200 71.42500 71.78400 72.31900 72.43000 72.56500 73.17200 73.13300 73.30700 73.09000 73.47400 73.72200 73.92600 74.18600 74.40800 74.08000 74.85500 75.13900 75.43300 75.00600 75.64100 75.93600 75.72100 76.12400 76.46700 76.49100 76.75500 76.76000 76.30800 76.83300 76.99900 77.28400 75.89200 75.39000 76.06400 NA NA

8.3 Funciones

En esta sección, se describen y ejemplifican las principales funciones de dplyr.

8.3.1 select()

La función select() selecciona (y opcionalmente renombra) columnas de un data frame con base en sus nombres.

# Selección de las columnas ADM0_ISO, NAME, POP_EST, GDP_MD
paises |>
  select(ADM0_ISO, NAME, POP_EST, GDP_MD)
# A tibble: 201 × 4
   ADM0_ISO NAME              POP_EST   GDP_MD
   <chr>    <chr>               <dbl>    <dbl>
 1 IDN      Indonesia       270625568  1119190
 2 MYS      Malaysia         31949777   364681
 3 CHL      Chile            18952038   282318
 4 BOL      Bolivia          11513100    40895
 5 PER      Peru             32510453   226848
 6 ARG      Argentina        44938712   445445
 7 GBR      United Kingdom   67366465  2863166
 8 CYP      Cyprus            1198575    24948
 9 IND      India          1366417754  2868929
10 CHN      China          1405862845 14762473
# ℹ 191 more rows

Cambio de nombres de columnas:

# Selección y cambio de nombre de las columnas 
# ADM0_ISO, NAME, POP_EST, GDP_MD
paises |>
  select(CODIGO_ISO_3 = ADM0_ISO,
         NOMBRE = NAME,
         POBLACION_ESTIMADA = POP_EST,
         PIB_MD = GDP_MD)
# A tibble: 201 × 4
   CODIGO_ISO_3 NOMBRE         POBLACION_ESTIMADA   PIB_MD
   <chr>        <chr>                       <dbl>    <dbl>
 1 IDN          Indonesia               270625568  1119190
 2 MYS          Malaysia                 31949777   364681
 3 CHL          Chile                    18952038   282318
 4 BOL          Bolivia                  11513100    40895
 5 PER          Peru                     32510453   226848
 6 ARG          Argentina                44938712   445445
 7 GBR          United Kingdom           67366465  2863166
 8 CYP          Cyprus                    1198575    24948
 9 IND          India                  1366417754  2868929
10 CHN          China                  1405862845 14762473
# ℹ 191 more rows

El operador : permite seleccionar un rango de columnas continuas:

# Selección de las columnas desde CONTINENT hasta INCOME_GRP
paises |>
  select(CONTINENT:INCOME_GRP)
# A tibble: 201 × 6
   CONTINENT     REGION_UN SUBREGION          REGION_WB       ECONOMY INCOME_GRP
   <chr>         <chr>     <chr>              <chr>           <chr>   <chr>     
 1 Asia          Asia      South-Eastern Asia East Asia & Pa… 4. Eme… 4. Lower …
 2 Asia          Asia      South-Eastern Asia East Asia & Pa… 6. Dev… 3. Upper …
 3 South America Americas  South America      Latin America … 5. Eme… 3. Upper …
 4 South America Americas  South America      Latin America … 5. Eme… 4. Lower …
 5 South America Americas  South America      Latin America … 5. Eme… 3. Upper …
 6 South America Americas  South America      Latin America … 5. Eme… 3. Upper …
 7 Europe        Europe    Northern Europe    Europe & Centr… 1. Dev… 1. High i…
 8 Asia          Asia      Western Asia       Europe & Centr… 6. Dev… 2. High i…
 9 Asia          Asia      Southern Asia      South Asia      3. Eme… 4. Lower …
10 Asia          Asia      Eastern Asia       East Asia & Pa… 3. Eme… 3. Upper …
# ℹ 191 more rows

Selección de todas las columnas que cumplen una condición:

# Selección de las columnas numéricas
paises |>
  select(where(is.numeric))
# A tibble: 201 × 2
      POP_EST   GDP_MD
        <dbl>    <dbl>
 1  270625568  1119190
 2   31949777   364681
 3   18952038   282318
 4   11513100    40895
 5   32510453   226848
 6   44938712   445445
 7   67366465  2863166
 8    1198575    24948
 9 1366417754  2868929
10 1405862845 14762473
# ℹ 191 more rows

8.3.2 filter()

La función filter() retorna un subconjunto de un data frame con todas las filas que satisfacen una condición (i.e. expresión lógica).

Puede utilizar los operadores relacionales:

  • == (igual que) Note la diferencia con el operador de asignación (=)
  • != (diferente de)
  • > (estrictamente mayor que), >= (mayor o igual que)
  • < (estrictamente menor que), <= (menor o igual que)

Y los operadores lógicos:

  • & (AND o Y lógico)
  • | (OR u O lógico)
  • ! (NOT o NO lógico)

Ejemplos de uso de expresiones y operadores lógicos:

# Países de Asia con ingresos alto y en la OCDE
# 
paises |>
  filter(CONTINENT == 'Asia' & INCOME_GRP == '1. High income: OECD')
# A tibble: 3 × 10
  ADM0_ISO NAME       CONTINENT REGION_UN SUBREGION REGION_WB ECONOMY INCOME_GRP
  <chr>    <chr>      <chr>     <chr>     <chr>     <chr>     <chr>   <chr>     
1 ISR      Israel     Asia      Asia      Western … Middle E… 2. Dev… 1. High i…
2 KOR      South Kor… Asia      Asia      Eastern … East Asi… 4. Eme… 1. High i…
3 JPN      Japan      Asia      Asia      Eastern … East Asi… 1. Dev… 1. High i…
# ℹ 2 more variables: POP_EST <dbl>, GDP_MD <dbl>
# Países de América del Norte o de América del Sur
paises |>
  filter(CONTINENT == 'North America' | CONTINENT == 'South America')
# A tibble: 35 × 10
   ADM0_ISO NAME      CONTINENT REGION_UN SUBREGION REGION_WB ECONOMY INCOME_GRP
   <chr>    <chr>     <chr>     <chr>     <chr>     <chr>     <chr>   <chr>     
 1 CHL      Chile     South Am… Americas  South Am… Latin Am… 5. Eme… 3. Upper …
 2 BOL      Bolivia   South Am… Americas  South Am… Latin Am… 5. Eme… 4. Lower …
 3 PER      Peru      South Am… Americas  South Am… Latin Am… 5. Eme… 3. Upper …
 4 ARG      Argentina South Am… Americas  South Am… Latin Am… 5. Eme… 3. Upper …
 5 SUR      Suriname  South Am… Americas  South Am… Latin Am… 6. Dev… 3. Upper …
 6 GUY      Guyana    South Am… Americas  South Am… Latin Am… 6. Dev… 4. Lower …
 7 CRI      Costa Ri… North Am… Americas  Central … Latin Am… 5. Eme… 3. Upper …
 8 NIC      Nicaragua North Am… Americas  Central … Latin Am… 6. Dev… 4. Lower …
 9 BRA      Brazil    South Am… Americas  South Am… Latin Am… 3. Eme… 3. Upper …
10 URY      Uruguay   South Am… Americas  South Am… Latin Am… 5. Eme… 3. Upper …
# ℹ 25 more rows
# ℹ 2 more variables: POP_EST <dbl>, GDP_MD <dbl>
# Países no europeos
paises |>
  filter(!(CONTINENT == 'Europe'))
# A tibble: 156 × 10
   ADM0_ISO NAME      CONTINENT REGION_UN SUBREGION REGION_WB ECONOMY INCOME_GRP
   <chr>    <chr>     <chr>     <chr>     <chr>     <chr>     <chr>   <chr>     
 1 IDN      Indonesia Asia      Asia      South-Ea… East Asi… 4. Eme… 4. Lower …
 2 MYS      Malaysia  Asia      Asia      South-Ea… East Asi… 6. Dev… 3. Upper …
 3 CHL      Chile     South Am… Americas  South Am… Latin Am… 5. Eme… 3. Upper …
 4 BOL      Bolivia   South Am… Americas  South Am… Latin Am… 5. Eme… 4. Lower …
 5 PER      Peru      South Am… Americas  South Am… Latin Am… 5. Eme… 3. Upper …
 6 ARG      Argentina South Am… Americas  South Am… Latin Am… 5. Eme… 3. Upper …
 7 CYP      Cyprus    Asia      Asia      Western … Europe &… 6. Dev… 2. High i…
 8 IND      India     Asia      Asia      Southern… South As… 3. Eme… 4. Lower …
 9 CHN      China     Asia      Asia      Eastern … East Asi… 3. Eme… 3. Upper …
10 ISR      Israel    Asia      Asia      Western … Middle E… 2. Dev… 1. High i…
# ℹ 146 more rows
# ℹ 2 more variables: POP_EST <dbl>, GDP_MD <dbl>
# Países de Europa en el G7
# solo con las columnas ADM0_ISO, NAME, POP_EST
paises |>
  filter(CONTINENT == "Europe" & ECONOMY == "1. Developed region: G7") |>
  select(ADM0_ISO, NAME, POP_EST) |>
  kable()
ADM0_ISO NAME POP_EST
GBR United Kingdom 67366465
FRA France 67692632
DEU Germany 83132799
ITA Italy 60297396
# Países con población mayor o igual al promedio
#   El argumento lógico na.rm de mean() 
#   indica si los valores NA ("not available") 
#   deben ser removidos antes del cálculo
paises |>
  filter(POP_EST >= mean(POP_EST, na.rm = TRUE)) |>
  select(ADM0_ISO, NAME, POP_EST)
# A tibble: 36 × 3
   ADM0_ISO NAME              POP_EST
   <chr>    <chr>               <dbl>
 1 IDN      Indonesia       270625568
 2 ARG      Argentina        44938712
 3 GBR      United Kingdom   67366465
 4 IND      India          1366417754
 5 CHN      China          1405862845
 6 ETH      Ethiopia        112078730
 7 KEN      Kenya            52573973
 8 TZA      Tanzania         58005463
 9 FRA      France           67692632
10 KOR      South Korea      51709098
# ℹ 26 more rows

Condiciones relacionadas con valores NA (nulos):

# Filas con valor NA en la columna 2022 (año 2022)
# del conjunto de datos de esperanza de vida
esperanza_vida |>
  select(`Country Name`, `2022`) |>
  filter(is.na(`2022`))
# A tibble: 9 × 2
  `Country Name`           `2022`
  <chr>                     <dbl>
1 Andorra                      NA
2 American Samoa               NA
3 Curacao                      NA
4 Cayman Islands               NA
5 Not classified               NA
6 Monaco                       NA
7 Northern Mariana Islands     NA
8 Palau                        NA
9 San Marino                   NA

Note como en el bloque anterior las columnas Country Name y 2022 deben escribirse entre comillas inversas debido a que una contiene espacios y la otra comienza con un número.

La función tidyr::drop_na() remueve las filas con valores NA en una o varias columnas.

# Filas con valor diferente a NA en la columna 2022
esperanza_vida |>
  select(`Country Name`,
         `2022`) |>
  drop_na(`2022`)
# A tibble: 257 × 2
   `Country Name`              `2022`
   <chr>                        <dbl>
 1 Aruba                         75.0
 2 Africa Eastern and Southern   62.9
 3 Afghanistan                   62.9
 4 Africa Western and Central    57.6
 5 Angola                        61.9
 6 Albania                       76.8
 7 Arab World                    71.2
 8 United Arab Emirates          79.2
 9 Argentina                     76.1
10 Armenia                       73.4
# ℹ 247 more rows
# Filas con valor diferente a NA en cualquier columna
penguins |>
  select(species,
         bill_length_mm,
         bill_depth_mm,
         flipper_length_mm,
         body_mass_g,
         sex) |>
  drop_na()
# A tibble: 333 × 6
   species bill_length_mm bill_depth_mm flipper_length_mm body_mass_g sex   
   <fct>            <dbl>         <dbl>             <int>       <int> <fct> 
 1 Adelie            39.1          18.7               181        3750 male  
 2 Adelie            39.5          17.4               186        3800 female
 3 Adelie            40.3          18                 195        3250 female
 4 Adelie            36.7          19.3               193        3450 female
 5 Adelie            39.3          20.6               190        3650 male  
 6 Adelie            38.9          17.8               181        3625 female
 7 Adelie            39.2          19.6               195        4675 male  
 8 Adelie            41.1          17.6               182        3200 female
 9 Adelie            38.6          21.2               191        3800 male  
10 Adelie            34.6          21.1               198        4400 male  
# ℹ 323 more rows

8.3.3 arrange()

La función arrange() cambia el orden de las filas de un data frame de acuerdo con los valores de las columnas seleccionadas.

# Ordenamiento ascendente por las columnas POP_EST y GDP_MD
paises |>
  arrange(POP_EST, GDP_MD) |>
  select(NAME, POP_EST, GDP_MD)
# A tibble: 201 × 3
   NAME                    POP_EST GDP_MD
   <chr>                     <dbl>  <dbl>
 1 Vatican                     825    -99
 2 Antarctica                 4490    898
 3 Cyprus U.N. Buffer Zone   10000    280
 4 Tuvalu                    11646     47
 5 Nauru                     12581    118
 6 Palau                     18008    268
 7 San Marino                33860   1655
 8 Liechtenstein             38019   6876
 9 Monaco                    38964   7188
10 St. Kitts and Nevis       52834   1053
# ℹ 191 more rows

Por defecto, las columnas se ordenan de manera acendente. Si se desea un orden descendente, puede utilizarse la función desc().

# Ordenamiento descendente por las columnas POP_EST y GDP_MD
paises |>
  arrange(desc(POP_EST), desc(GDP_MD)) |>
  select(NAME, POP_EST, GDP_MD)
# A tibble: 201 × 3
   NAME                        POP_EST   GDP_MD
   <chr>                         <dbl>    <dbl>
 1 China                    1405862845 14762473
 2 India                    1366417754  2868929
 3 United States of America  331595460 21542705
 4 Indonesia                 270625568  1119190
 5 Pakistan                  216565318   278221
 6 Brazil                    211049527  1839758
 7 Nigeria                   200963599   448120
 8 Bangladesh                163046161   302571
 9 Russia                    144373535  1699876
10 Mexico                    127575529  1268870
# ℹ 191 more rows

Los valores NA (si hay alguno) se ubican al final de cualquier ordenamiento.

8.3.4 mutate()

La función mutate() crea o modifica columnas en un data frame.

# Creación de la columna GDP_PC,
# correspondiente al producto interno bruto per cápita en dólares
paises <-
  paises |>
  mutate(GDP_PC = (GDP_MD * 1000000) / POP_EST)

# Despliegue
paises |>
  select(NAME, GDP_MD, POP_EST, GDP_PC)
# A tibble: 201 × 4
   NAME             GDP_MD    POP_EST GDP_PC
   <chr>             <dbl>      <dbl>  <dbl>
 1 Indonesia       1119190  270625568  4136.
 2 Malaysia         364681   31949777 11414.
 3 Chile            282318   18952038 14896.
 4 Bolivia           40895   11513100  3552.
 5 Peru             226848   32510453  6978.
 6 Argentina        445445   44938712  9912.
 7 United Kingdom  2863166   67366465 42501.
 8 Cyprus            24948    1198575 20815.
 9 India           2868929 1366417754  2100.
10 China          14762473 1405862845 10501.
# ℹ 191 more rows

8.3.5 group_by() y summarize()

La función summarize() se utiliza generalmente junto con la función group_by() para realizar cálculos en grupos de filas de un data frame. group_by() agrupa las filas y summarize() realiza los cálculos (ej. sumas, promedios) en las columnas, para cada grupo. El resultado es un nuevo data frame con una fila por grupo. Si no hay agrupación, se retorna una sola fila correspondiente a los cálculos para todo el data frame.

Ejemplos de cálculos en grupos:

# Mínimo, máximo, promedio de población y cantidad de países
# para cada región de la ONU
paises |>
  group_by(REGION_UN) |>
  summarize(
    POP_EST_MIN = min(POP_EST, na.rm = TRUE),
    POP_EST_MAX = max(POP_EST, na.rm = TRUE),
    POP_EST_MEAN = mean(POP_EST, na.rm = TRUE),
    n = n()
  )
# A tibble: 6 × 5
  REGION_UN  POP_EST_MIN POP_EST_MAX POP_EST_MEAN     n
  <chr>            <dbl>       <dbl>        <dbl> <int>
1 Africa           97625   200963599    23381240.    56
2 Americas         52834   331595460    28909700.    35
3 Antarctica        4490        4490        4490      1
4 Asia             10000  1405862845    91256711.    50
5 Europe             825   144373535    16615735.    45
6 Oceania          11646    25368867     2970679.    14

La función n() cuenta la cantidad de filas en un grupo.

# Cantidad de países por región y subregión de la ONU
paises |>
  group_by(REGION_UN, SUBREGION) |>
  summarize(
    N = n()
  ) |>
  arrange(desc(N)) |>
  kable()
REGION_UN SUBREGION N
Africa Eastern Africa 19
Asia Western Asia 19
Africa Western Africa 16
Europe Southern Europe 16
Americas Caribbean 13
Americas South America 12
Asia South-Eastern Asia 11
Europe Eastern Europe 10
Europe Northern Europe 10
Africa Middle Africa 9
Asia Southern Asia 9
Europe Western Europe 9
Americas Central America 8
Africa Northern Africa 7
Asia Eastern Asia 6
Africa Southern Africa 5
Asia Central Asia 5
Oceania Micronesia 5
Oceania Melanesia 4
Oceania Polynesia 3
Americas Northern America 2
Oceania Australia and New Zealand 2
Antarctica Antarctica 1

Ejemplo de cálculos sin agrupamiento:

# Promedio de GDP_PC y cantidad de países del mundo
paises |>
  summarise(GDP_PC_MEAN = mean(GDP_PC, na.rm = TRUE),
            n = n())
# A tibble: 1 × 2
  GDP_PC_MEAN     n
        <dbl> <int>
1      15836.   201

8.3.6 Otras

8.3.6.1 distinct()

La función distinct() retorna las combinaciones únicas de filas en un data frame.

# Valores distintos de la columna CONTINENT

paises |>
  distinct(CONTINENT) |>
  kable()
CONTINENT
Asia
South America
Europe
Africa
North America
Oceania
Antarctica
Seven seas (open ocean)

8.3.6.2 count()

Una forma alternativa a summarize() para realizar un conteo es con la función count():

# Conteo de países por continente
paises |>
  count(CONTINENT)
# A tibble: 8 × 2
  CONTINENT                   n
  <chr>                   <int>
1 Africa                     54
2 Antarctica                  1
3 Asia                       49
4 Europe                     45
5 North America              23
6 Oceania                    14
7 Seven seas (open ocean)     3
8 South America              12
# Expresión equivalente con summarize
paises |>
  group_by(CONTINENT) |>
  summarize(n = n()) |>
  kable()
CONTINENT n
Africa 54
Antarctica 1
Asia 49
Europe 45
North America 23
Oceania 14
Seven seas (open ocean) 3
South America 12

8.4 Ejercicios

Utilice las funciones de dplyr para responder a las siguientes preguntas sobre el conjunto de datos paises:

  1. ¿Cuántos países hay en cada región del Banco Mundial?
  2. ¿Cuál es el mínimo, máximo y promedio de producto interno bruto per cápita en el continente africano?
  3. ¿Cuál es el promedio de producto interno bruto per cápita por región del Banco Mundial?

8.5 Recursos de interés

RStudio. (2017). Data transformation with dplyr::Cheat Sheet. https://github.com/rstudio/cheatsheets/blob/45c1e642468695830fd8b724587ccfe8901e2185/data-transformation.pdf