Presentación

Esta publicación tiene dos objetivos, uno personal y otro general. El objetivo personal es tener en limpio y siempre disponible un script de consulta para el uso de la API del Banco Mundial utilizando R. El segundo objetivo, el general, es simplemente compartirlo a todo aquel que guste.

No asumo que mi código sea el más eficiente o esté libre de errores, así que cualquier corrección, sugerencia o comentario házmelo saber por este medio o a través de mi twitter ecodiegoale.

Además, nunca está de más revisar stackoverflow, github, rpubs o preguntarle a ChatGPT.

Aviso: Si algún link no abre con click izquierdo, trata con el derecho y abrir en otra ventana o pestaña.

Contenido

En este blog usaré la API del Banco Mundial de una manera muy sencilla utilizando principalmente la librería de tidyverse. No me detendré a explicar mucho sobre la manipulación de datos con esta librería, de esto tengo varias entradas, además que puedes hacer uso de herramientas de Inteligencia Artificial para que te ayude con eso. Lo importante en este blog será el uso de la librería {WDI}, la cual proporciona una interfaz sencilla para acceder a la base de datos del Banco Mundial, conocida como World Development Indicators (WDI). Esta base de datos es una de las fuentes más completas de indicadores económicos, sociales y demográficos a nivel mundial, con datos para más de 200 países y regiones desde 1960. Los indicadores abarcan diferentes áreas además de la económica, como educación, salud, comercio, medio ambiente, tecnología, entre otros.

En esta entrada no solo mostraré cómo usar {WDI} para la descarga y manipulación de estos indicadores para diversos países y años en un solo paso, también mostraré un uso muy básico de {naniar} para identificar y visualizar valores faltantes en los datos descargados. Esto es especialmente relevante porque muchos países, particularmente aquellos de ingresos bajos, no cuentan con datos disponibles para periodos anteriores a fechas recientes. Usaremos {naniar} únicamente para resaltar estas ausencias, sin aplicar ningún tratamiento adicional a los valores faltantes.

Preparación

Lo primero será definir tu directorio de trabajo y cargar las librerías necesarias para el análisis.

#setwd("C:/Users/tu carpeta")

rm(list = ls()) #para borrar todos los objetos en la memoria de la consola
options(scipen=999) #para desactivar la notación científica

#Si no cuentas con los paquetes, usa el comando install.packages("ejemplo")

library(WDI)
library(tidyverse)
library(readxl)

Conforme avancemos en el blog haré mención de cuando estemos usando las librerías cargadas.

Cómo comenzar a usar la API del Banco Mundial con {WDI}

Paso 1: ID de los indicadores

Como dije en la introducción, esta base de datos contiene cientos, sino miles, de indicadores para diversos países, regiones y años (desde 1960 para aquellos donde hay información), y si revisas la documentación de {WDI} (realmente te recomiendo hacerlo, siempre hay que revisar la documentación de las librerías que vamos a utilizar, esto puede ahorrarnos muchas horas de trabajo) podrás ver que hay diversas formas de acceder a los indicadores y países de tu interés los cuales dependerán de tu objetivo o pregunta de investigación. Sin importar el método que utilices, lo cierto es que necesitas dos insumos básicos, el país y el indicador.

Los países vienen codificados en la base de WDI (y en muchas otras, como la Penn World Table, OCDE…) en ISO 3166-1 alpha-3, el cual es un estándar internacional de tres letras que identifica de manera única a cada país. Los indicadores del WDI son codificados por el Banco Mundial.

Lo primero será buscar el ID o código de los indicadores que nos importan, hay varias maneras de buscarlos, uno es que entres directamente al sitio web del Banco Mundial (World Bank), entres al DataBank del World Development Indicators, selecciones tu indicador, los países y los años, descargues el libro de excel o el formato de tu preferencia, y una vez que lo abras podrás ver que en los encabezados de las columnas viene el código.

Por ejemplo, para la inflación con base en el índice de precios al consumidor de cada país, la descarga luciría así:

Como podemos ver, para Inflation, consumer prices (annual %) el código de la serie es FP.CPI.TOTL.ZG, e incluso podemos ver los códigos para los países disponibles. Sin embargo, hacer esto es tedioso, ocupa memoria (la descarga de cada conjunto de datos) y no es muy eficiente. Por lo que enseguida mostraré cómo hacerlo con algunas funciones de {WDI}.

La función que usaremos es WDIsearch(). Esta función permite buscar indicadores disponibles en la base de datos del Banco Mundial usando palabras clave, el argumento principal es de tipo string (cadena de texto), que debe ser la palabra clave o frase. El argumento opcional es field que puede contener name, description y indicator, todos estos como cadenas de texto; name indicará que solo se buscará el nombre del indicador, description las descripciones de los indicadores y indicator el ID.

glimpse(WDIsearch("gdp"))
## Rows: 540
## Columns: 2
## $ indicator <chr> "5.51.01.10.gdp", "6.0.GDP_current", "6.0.GDP_growth", "6.0.…
## $ name      <chr> "Per capita GDP growth", "GDP (current $)", "GDP growth (ann…

Aquí usé glimpse() por motivos ilustrativos, como observamos, la búsqueda arrojó 540 indicadores, pues muchos indicadores utilizan o están relacionados con el PIB, por ejemplo, podemos tener el PIB en términos nominales (en moneda local), constantes (en moneda local y deflactado con su propio índice de precios), en dólares, dólares internacionales, algún indicador como porcentaje del PIB, etc. Otro aspecto importante es que la búsqueda es un dataframe de dos columnas, indicator (ID) y name.

Podemos reducir la búsqueda utilizando expresiones regulares. Una expresión regular (o regex, por su abreviatura en inglés) es una secuencia de caracteres que define un patrón de búsqueda. En R, las expresiones regulares se utilizan para buscar, extraer o manipular texto de manera eficiente dentro de cadenas de caracteres. A continuación, mostraré una manera sencilla, aclaro que no soy experto en expresiones regulares, pero con la asistencia de inteligencia artificial es mucho más fácil.

Si lo que nos interesa del PIB es el PIB per cápita podemos modificar la búsqueda como sigue:

as.tibble(WDIsearch('gdp.*capita'))
## # A tibble: 29 × 2
##    indicator            name                                                    
##    <chr>                <chr>                                                   
##  1 6.0.GDPpc_constant   "GDP per capita, PPP (constant 2011 international $) "  
##  2 CC.GHG.MEMG.GC       "Macro drivers of GHG emissions growth in the period 20…
##  3 FB.DPT.INSU.PC.ZS    "Deposit insurance coverage (% of GDP per capita)"      
##  4 NE.GDI.FTOT.CR       "GDP expenditure on gross fixed capital formation (in I…
##  5 NE.GDI.FTOT.SNA08.CR "GDP expenditure on gross fixed capital formation (in I…
##  6 NV.AGR.PCAP.KD.ZG    "Real agricultural GDP per capita growth rate (%)"      
##  7 NY.GDP.PCAP.CD       "GDP per capita (current US$)"                          
##  8 NY.GDP.PCAP.CN       "GDP per capita (current LCU)"                          
##  9 NY.GDP.PCAP.KD       "GDP per capita (constant 2015 US$)"                    
## 10 NY.GDP.PCAP.KD.ZG    "GDP per capita growth (annual %)"                      
## # ℹ 19 more rows
# Puedes usar View(WDIsearch('gdp.*capita')) en RStudio

En el comando anterior, la cadena 'gdp.*capita' utiliza una expresión regular para buscar indicadores que incluyan las palabras “gdp” y “capita”, aunque puedan tener otros caracteres entre ellas. Dentro de la expresión estamos buscando gdp y capita en ese orden, mientras que .* indica cualquier cantidad de caracteres (letras, números o símbolos), incluidos ninguno.

Si lo que nos interesa es, por ejemplo, una comparación internacional de los niveles del PIB per cápita, el indicador más conveniente, a mi parecer, es GDP per capita, PPP (constant 2017 international $), cuyo ID es NY.GDP.PCAP.PP.KD. Este indicador mide el PIB por persona, ajustado por Paridad de Poder Adquisitivo (PPP), utilizando dólares internacionales constantes de 2017, es decir, mide el PIB por persona y ajusta los valores para reflejar las diferencias en los costos de vida y niveles de precios entre países, asimismo que usa precios de 2017 para eliminar el efecto de la inflación, facilitando comparaciones a lo largo del tiempo.

Ya tenemos las suficientes herramientas para buscar los indicadores y sus ID.

Paso 2: ID de los países

Como en el Paso 1, en este paso podríamos buscar la clave desde algún archivo descargado directamente del sitio web, pero nuevamente esto no es muy práctico. Vamos a explorar los países y sus claves desde R.

Primero, vamos a cargar un dataset interno de {WDI} llamado WDI_data.

data("WDI_data", package = "WDI")

Una vez cargado, podrás notar que no es un dataframe sino una lista.

class(WDI_data)
## [1] "list"

Dicha lista contiene 2 elementos:

length(WDI_data)
## [1] 2

Y cada elemento tiene su nombre:

names(WDI_data)
## [1] "series"  "country"

Ahora, vamos a extraer el segundo elemento, country, de la lista y guardarla en un objeto por separado. Primero, exploramos qué tipo de objeto está guardado en country.

class(WDI_data[["country"]])
## [1] "data.frame"

Vemos que es un marco de datos, por lo que cuando extraigamos el objeto de la lista tendremos un dataframe, dicho dataframe contendrá información adicional sobre los países, como su nombre, sus claves en iso3c e iso2c (nosotros usaremos el iso3c), la región geográfica a la que pertenecen, el tipo de país por nivel de ingreso, la capital, entre otros datos.

countries <- WDI_data[["country"]]

Rápidamente vamos a explorar este objeto:

glimpse(countries)
## Rows: 299
## Columns: 9
## $ iso3c     <chr> "ABW", "AFE", "AFG", "AFR", "AFW", "AGO", "ALB", "AND", "ARB…
## $ iso2c     <chr> "AW", "ZH", "AF", "A9", "ZI", "AO", "AL", "AD", "1A", "AE", …
## $ country   <chr> "Aruba", "Africa Eastern and Southern", "Afghanistan", "Afri…
## $ region    <chr> "Latin America & Caribbean", "Aggregates", "South Asia", "Ag…
## $ capital   <chr> "Oranjestad", "", "Kabul", "", "", "Luanda", "Tirane", "Ando…
## $ longitude <chr> "-70.0167", "", "69.1761", "", "", "13.242", "19.8172", "1.5…
## $ latitude  <chr> "12.5167", "", "34.5228", "", "", "-8.81155", "41.3317", "42…
## $ income    <chr> "High income", "Aggregates", "Low income", "Aggregates", "Ag…
## $ lending   <chr> "Not classified", "Aggregates", "IDA", "Aggregates", "Aggreg…

Algo que quiero destacar es que si tú requieres un análisis agregado por región, en la columna region se incluye no solo la región a la que pertenece el país, sino regiones agregadas, las cuales tienen su propio iso3c, así que si ese es tu interés queda de ti, en este blog usaré países por separado.

Con este dataframe podemos explorar y ver las claves de los países que nos interesen:

head(countries) %>% knitr::kable()
iso3c iso2c country region capital longitude latitude income lending
ABW AW Aruba Latin America & Caribbean Oranjestad -70.0167 12.5167 High income Not classified
AFE ZH Africa Eastern and Southern Aggregates Aggregates Aggregates
AFG AF Afghanistan South Asia Kabul 69.1761 34.5228 Low income IDA
AFR A9 Africa Aggregates Aggregates Aggregates
AFW ZI Africa Western and Central Aggregates Aggregates Aggregates
AGO AO Angola Sub-Saharan Africa Luanda 13.242 -8.81155 Lower middle income IBRD

Como podemos ver en el cuadro anterior, el código de los países están en la columna iso3c. Puedes explorar este dataframe y elegir los países de tu interés, para fines de este blog seleccionaré los países de América Latina y el Caribe.

Paso 3: Descargar las series con WDI()

Ahora, vamos a ver cómo se descargan las series utilizando la función WDI(). Esta función tiene dos argumentos principales, pero en total posee ocho.

args(WDI)
## function (country = "all", indicator = "NY.GDP.PCAP.KD", start = 1960, 
##     end = NULL, extra = FALSE, cache = NULL, latest = NULL, language = "en") 
## NULL
  • country: Especifica los países para los que se desean los datos y debe ser un vector de caracteres.
    • Si country = “all”, se descargarán los datos para todos los países disponibles. Si solo se desea ciertos países o regiones debemos poner algún vector con los iso3c.
# country = c("MEX", "USA")
  • indicator: Especifica los indicadores a descargar. Igualmente debe ser un vector de caracteres
# indicator = c("NY.GDP.PCAP.PP.KD", "NY.GDP.PCAP.KD")
  • start: Año de inicio para los datos a descargar y debe ser un número entero. Si no se especifica, incluye datos desde el primer año disponible.
# start = 1970
  • end: Año de finalización para los datos a descargar y debe ser un número entero. Si no se especifica, incluye datos hasta el último año disponible.
# end = 1990

Conocer la utilidad del resto de argumentos se deja al lector.

Ahora, vamos con un ejemplo. Vamos a descargar la inflación y el PIB per cápita.

data <- WDI(
  indicator = c("gdpc_pc_pp" = "NY.GDP.PCAP.PP.KD", 
                "inflation" = "FP.CPI.TOTL.ZG"),
  # Nota como en "indicator" renombré las variables, si no lo haces tus columnas tendrán por nombre el ID
  country = c("MX", "CA", "US"), 
  start = 2000, 
  end = 2012
  )

El resultado es un dataframe que luce así.

glimpse(data)
## Rows: 39
## Columns: 6
## $ country    <chr> "Canada", "Canada", "Canada", "Canada", "Canada", "Canada",…
## $ iso2c      <chr> "CA", "CA", "CA", "CA", "CA", "CA", "CA", "CA", "CA", "CA",…
## $ iso3c      <chr> "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CAN", "CA…
## $ year       <int> 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,…
## $ gdpc_pc_pp <dbl> 47667.43, 48036.63, 48943.54, 49381.60, 50436.29, 51564.85,…
## $ inflation  <dbl> 2.7194400, 2.5251201, 2.2583944, 2.7585632, 1.8572587, 2.21…
head(data) %>% knitr::kable()
country iso2c iso3c year gdpc_pc_pp inflation
Canada CA CAN 2000 47667.43 2.719440
Canada CA CAN 2001 48036.63 2.525120
Canada CA CAN 2002 48943.54 2.258394
Canada CA CAN 2003 49381.60 2.758563
Canada CA CAN 2004 50436.29 1.857259
Canada CA CAN 2005 51564.85 2.213552

Si visualizas tu dataframe en RStudio podrás notar que bajo el nombre de las columnas con los indicadores viene su descripción.

# View(data)

Una aplicación para América Latina y el Caribe

Como ya vimos, {WDI} es muy sencilla de usar, y el objeto resultante es un dataframe bastante limpio y ordenado, formato tidy. Ahora, vamos con un ejemplo práctico que incluya una descarga masiva, estadística descriptica y una visualización apropiada y atractiva.

No me detendré mucho a explicar nuevamente las funciones de {WDI} ni la manipulación de datos, pues usaré principalmente {dplyr}, y sobre este paquete hay infinidad de recursos (o puedes copiar y pegar el código que presentaré en una conversación con ChatGPT y pedirle que te lo explique a detalle).

Descarga

Primero, quiero todos los países de América Latina y el Caribe. Así que necesito un vector de caracteres con los iso3c de dichos países.

Recordemos nuestro dataframe countries.

countries %>% select(region) %>% unique()
##                        region
## 1   Latin America & Caribbean
## 2                  Aggregates
## 3                  South Asia
## 6          Sub-Saharan Africa
## 7       Europe & Central Asia
## 10 Middle East & North Africa
## 13        East Asia & Pacific
## 34              North America

Ahora que sabemos el nombre de la región de interés, podemos crear el vector como sigue.

alc <- countries %>% 
  filter(region == "Latin America & Caribbean") %>% 
  select(iso3c) %>% 
  pull()

alc
##  [1] "ABW" "ARG" "ATG" "BHS" "BLZ" "BOL" "BRA" "BRB" "CHL" "COL" "CRI" "CUB"
## [13] "CUW" "CYM" "DMA" "DOM" "ECU" "GRD" "GTM" "GUY" "HND" "HTI" "JAM" "KNA"
## [25] "LCA" "MAF" "MEX" "NIC" "PAN" "PER" "PRI" "PRY" "SLV" "SUR" "SXM" "TCA"
## [37] "TTO" "URY" "VCT" "VEN" "VGB" "VIR"

La búsqueda de los indicadores es más artesanal y ya me explayé en cómo debe hacerse.

Yo usaré algunas variables macroeconómicas clásicas.

series <- c(
  "gdpc_pc_pp" = "NY.GDP.PCAP.PP.KD", # GDP per capita PPP constant 2021 international $
  "gov_con_gdp" = "NE.CON.GOVT.ZS", # General government final consumption expenditure (% of GDP)
  "gfcf_gdp" = "NE.GDI.FTOT.ZS",    # Gross fixed capital formation (% of GDP)
  "gds_gdp" = "NY.GDS.TOTL.ZS"     # Gross domestic savings (% of GDP)
)

Finalmente, descargamos. Vamos a suponer que quiero los datos para el periodo 2000-2005.

data_alc <- WDI(
  indicator = series,
  country = alc,
  start = 2000, 
  end = 2005
  )

El resultado luce así:

glimpse(data_alc)
## Rows: 252
## Columns: 8
## $ country     <chr> "Antigua and Barbuda", "Antigua and Barbuda", "Antigua and…
## $ iso2c       <chr> "AG", "AG", "AG", "AG", "AG", "AG", "AR", "AR", "AR", "AR"…
## $ iso3c       <chr> "ATG", "ATG", "ATG", "ATG", "ATG", "ATG", "ARG", "ARG", "A…
## $ year        <int> 2000, 2001, 2002, 2003, 2004, 2005, 2000, 2001, 2002, 2003…
## $ gdpc_pc_pp  <dbl> 25552.72, 24019.59, 23962.97, 25141.10, 26308.86, 27698.22…
## $ gov_con_gdp <dbl> NA, NA, NA, NA, NA, NA, 13.784191, 14.156274, 12.235247, 1…
## $ gfcf_gdp    <dbl> NA, NA, NA, NA, NA, NA, 16.19265, 14.17912, 11.96065, 15.1…
## $ gds_gdp     <dbl> NA, NA, NA, NA, NA, NA, 16.88380, 16.93174, 25.86633, 25.3…

{naniar} : Inspección de datos faltantes

Primero, como siempre, recomiendo darle una revisada a la documentación para conocer el abanico de funciones o cómo usar las mismas. Esta la puedes encontrar en este enlace.

Como siempre, cargamos la librería:

library(naniar)

La función vis_miss() nos ofrece una vista general de los valores faltantes en el conjunto de datos. Genera un gráfico donde cada celda representa un valor en el dataframe: las celdas sombreadas indican datos faltantes (NA). En este caso, incluyo un tema que rota los textos del eje X para facilitar la lectura de las variables (observa que la gramática es la misma que la de {ggplot2}, por lo que podrías personalizarlo a tu gusto).

vis_miss(data_alc) +
  theme(axis.text.x = element_text(angle = 90))

Este gráfico es especialmente útil para detectar patrones de valores faltantes en filas y columnas.

Ahora, si lo que queremos es visualizar los valores faltantes por variable, con gg_miss_var() podemos enfocarnos en un análisis por variable, generando un gráfico de barras que muestra cuántos valores faltantes hay en cada columna del dataframe. En este ejemplo, he activado la opción show_pct = TRUE para que también se muestre el porcentaje de valores faltantes:

# Visualización de NAs por variable
gg_miss_var(data_alc, show_pct = TRUE)

Esto nos permite identificar rápidamente cuáles variables tienen más ausencias y qué tan significativas son en relación con el total de observaciones. Aunque no trataremos estos valores faltantes, esta exploración inicial es clave para decidir cómo proceder con los análisis.