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.
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.
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.
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 RStudioEn 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.
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.
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.
# 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 = 1970end: 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 = 1990Conocer 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)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).
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…
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.