Extracción de datos desde la API del DataMapper del FMI en R

sept. 29, 2025·
Roger Mario López Justiniano
Roger Mario López Justiniano
· 11 min de lectura

En una entrada anterior mostré cómo acceder a los datos de la CEPAL a través de su API. Si bien esto es bastante útil, está restringido a los países latinoamericanos. En esta entrada, por tanto, me gustaría extender la extracción de datos a fuentes más generales como, por ejemplo, el Fondo Monetario Internacional (FMI).

Por un lado, se pueden extraer de forma relativamente directa los datos del Data Mapper, que es bastante general y contiene la información para la mayoría de los análisis y comparaciones internacionale que se deseen realizar, ya sea de corte transversal o de panel. La información de la API se encuentra aquí y es relativamente fácil de consultar. Sobre esto nos enfocaremos en esta entrada.

Por otro lado, distintas organizaciones internacionales han dispuesto sus datos a través de un protocolo estándar, denominado SDMX, que permite acceder a los datos de forma más o menos homogénea. El FMI también dispone de una API SDMX, que se encuentra documentada aquí. En este caso, la extracción de datos es un poco más compleja, pero existen paquetes en R que facilitan la tarea. En particular, el paquete rsdmx es bastante útil para este propósito. Sin embargo, su uso será explicado en otra entrada.

Extracción de datos del Data Mapper del FMI

Para este caso, el FMI nos ofrece la API mediante la siguiente URL base https://www.imf.org/external/datamapper/api/v1/. A partir de ella cuatro endpoints principales, desde los cuales se pueden extraer los datos:

  • indicators: para obtener la lista de indicadores disponibles.
  • countries: para obtener la lista de países disponibles.
  • regions: para obtener la lista de regiones disponibles.
  • groups: para obtener la lista de grupos de países disponibles.

Para que se entienda la idea del endpoint basta colocar la siguiente URL en el navegador web de su preferencia https://www.imf.org/external/datamapper/api/v1/indicators. Esto nos devolverá texto plano en formato JSON con la lista de indicadores disponibles:

Por tanto, la idea es construir una función que nos permita extraer la información de estos endpoints en un formato más amigable para el análisis de datos y luego filtrar los indicadores o países que nos interesen.

Una función para extraer los catálogos

En primer lugar, vamos a utilizar la librería jsonlite (documentación aquí y aquí) que nos permitirá extraer la información desde la web.

La forma más sencilla de hacerlo es:

indicators <- jsonlite::fromJSON(txt='https://www.imf.org/external/datamapper/api/v1/indicators', simplifyVector = FALSE)

str(indicators, max.level = 2)
List of 2
 $ indicators:List of 133
  ..$ NGDP_RPCH         :List of 5
  ..$ NGDPD             :List of 5
  ..$ NGDPDPC           :List of 5
  ..$ PPPGDP            :List of 5
  ..$ PPPPC             :List of 5
  ..$ PPPSH             :List of 5
  ..$ PPPEX             :List of 5
  ..$ PCPIPCH           :List of 5
  ..$ PCPIEPCH          :List of 5
  ..$ LP                :List of 5
  ..$ BCA               :List of 5
  ..$ BCA_NGDPD         :List of 5
  ..$                   :List of 5
  ..$ LUR               :List of 5
  ..$ GGXCNL_NGDP       :List of 5
  ..$ GGXWDG_NGDP       :List of 5
  ..$ rev               :List of 5
  ..$ exp               :List of 5
  ..$ prim_exp          :List of 5
  ..$ ie                :List of 5
  ..$ pb                :List of 5
  ..$ d                 :List of 5
  ..$ rgc               :List of 5
  ..$ rltir             :List of 5
  ..$ extensive         :List of 5
  ..$ intensive         :List of 5
  ..$ total_theil       :List of 5
  ..$ SITC1_0           :List of 5
  ..$ SITC1_1           :List of 5
  ..$ SITC1_2           :List of 5
  ..$ SITC1_3           :List of 5
  ..$ SITC1_4           :List of 5
  ..$ SITC1_5           :List of 5
  ..$ SITC1_6           :List of 5
  ..$ SITC1_7           :List of 5
  ..$ SITC1_8           :List of 5
  ..$ SITC1_9           :List of 5
  ..$ SITC1_total       :List of 5
  ..$ DirectAbroad      :List of 5
  ..$ DirectIn          :List of 5
  ..$ PrivInexDI        :List of 5
  ..$ PrivInexDIGDP     :List of 5
  ..$ PrivOutexDI       :List of 5
  ..$ PrivOutexDIGDP    :List of 5
  ..$ Portfa            :List of 5
  ..$ Portfl            :List of 5
  ..$ EquityA           :List of 5
  ..$ EquityL           :List of 5
  ..$ DebtA             :List of 5
  ..$ DebtL             :List of 5
  ..$ OtherGov          :List of 5
  ..$ OtherA            :List of 5
  ..$ OtherL            :List of 5
  ..$ Deriv             :List of 5
  ..$ DebtForg          :List of 5
  ..$ GDP               :List of 5
  ..$ ka_new            :List of 5
  ..$ ka_in             :List of 5
  ..$ ka_out            :List of 5
  ..$ FM_ka             :List of 5
  ..$ Nonres_ka         :List of 5
  ..$ Res_ka            :List of 5
  ..$ Ka_eq             :List of 5
  ..$ Ka_bo             :List of 5
  ..$ Ka_mm             :List of 5
  ..$ Ka_ci             :List of 5
  ..$ Ka_dr             :List of 5
  ..$ Ka_cc             :List of 5
  ..$ Ka_fc             :List of 5
  ..$ Ka_gu             :List of 5
  ..$ Ka_di             :List of 5
  ..$ ka_ldi            :List of 5
  ..$ ka_ret            :List of 5
  ..$ ka_pct            :List of 5
  ..$ Reserves_ARA      :List of 5
  ..$ Reserves_M2       :List of 5
  ..$ Reserves_STD      :List of 5
  ..$ Reserves_M        :List of 5
  ..$ GRB_dummy         :List of 5
  ..$ GDI_TC            :List of 5
  ..$ GII_TC            :List of 5
  ..$ DEBT1             :List of 5
  ..$ Privatedebt_all   :List of 5
  ..$ HH_ALL            :List of 5
  ..$ NFC_ALL           :List of 5
  ..$ PVD_LS            :List of 5
  ..$ HH_LS             :List of 5
  ..$ NFC_LS            :List of 5
  ..$ PS_DEBT_GDP       :List of 5
  ..$ NFPS_DEBT_GDP     :List of 5
  ..$ GG_DEBT_GDP       :List of 5
  ..$ CG_DEBT_GDP       :List of 5
  ..$ GGXCNL_G01_GDP_PT :List of 5
  ..$ GGXONLB_G01_GDP_PT:List of 5
  ..$ GGCB_G01_PGDP_PT  :List of 5
  ..$ GGCBP_G01_PGDP_PT :List of 5
  ..$ GGR_G01_GDP_PT    :List of 5
  ..$ G_X_G01_GDP_PT    :List of 5
  ..$ G_XWDG_G01_GDP_PT :List of 5
  .. [list output truncated]
 $ api       :List of 2
  ..$ version      : chr "1"
  ..$ output-method: chr "json"

Que nos devulve una lista con indicadores y demás metatados, como ser el nombre (label), su descripción (description), entre otros. Para simplificar la lógica de extracción se condensan todos los pasos en la función get_catalog() que se define a continuación:

get_catalog <- function(path,
                        base = "https://www.imf.org/external/datamapper/api/v1") {
  raw <- jsonlite::fromJSON(sprintf("%s/%s", base, path), simplifyVector = FALSE)
  
  # si existe raw[[path]], úsalo; de lo contrario, usa raw
  obj <- if (!is.null(raw[[path]])) raw[[path]] else raw
  
  obj$api <- NULL  # quita metadatos
  
  tibble::tibble(
    code  = names(obj),
    label = vapply(obj, function(x) if (is.null(x$label)) NA_character_ else x$label,
                   character(1), USE.NAMES = FALSE)
  )
}

Con esta función podemos extraer los catálogos de indicadores, países, regiones y grupos de países y ordenarlos en un dataframe (o tibble) de la siguiente manera:

indicators <- get_catalog("indicators")

head(indicators, 10)
# A tibble: 10 × 2
   code      label                                          
   <chr>     <chr>                                          
 1 NGDP_RPCH "Real GDP growth"                              
 2 NGDPD     "GDP, current prices"                          
 3 NGDPDPC   "GDP per capita, current prices\n"             
 4 PPPGDP    "GDP, current prices"                          
 5 PPPPC     "GDP per capita, current prices"               
 6 PPPSH     "GDP based on PPP, share of world"             
 7 PPPEX     "Implied PPP conversion rate"                  
 8 PCPIPCH   "Inflation rate, average consumer prices"      
 9 PCPIEPCH  "Inflation rate, end of period consumer prices"
10 LP        "Population"                                   

Lo mismo podemos hacer con los países, regiones y grupos de países, aunque se deja al lector la reproducción con regiones y grupos:

countries <- get_catalog("countries")

head(countries, 10)
# A tibble: 10 × 2
   code  label               
   <chr> <chr>               
 1 ABW   Aruba               
 2 AFG   Afghanistan         
 3 AGO   Angola              
 4 AIA   Anguilla            
 5 ALB   Albania             
 6 ARE   United Arab Emirates
 7 ARG   Argentina           
 8 ARM   Armenia             
 9 ASM   American Samoa      
10 ATG   Antigua and Barbuda 

Extracción de datos específicos

Una vez que tenemos los códigos de los indicadores y países que nos interesan, podemos proceder a extraer los datos específicos. Para ello, el FMI también nos indica cómo consultar los indicadores. Por ejemplo, si quisiésemos extraer el crecimiento del PIB real (NGDP_RPCH) para Bolivia (BOL) entre los años 2015 a 2020, deberíamos consultar la siguiente URL: https://www.imf.org/external/datamapper/api/v1/NGDP_RPCH/BOL?periods=2015,2016,2017,2018,2019,2020:

En R podríamos extraerlo de la siguiente manera:

ngdp_bol <- jsonlite::fromJSON(txt='https://www.imf.org/external/datamapper/api/v1/NGDP_RPCH/BOL?periods=2015,2016,2017,2018,2019,2020', simplifyVector = FALSE)

ngdp_bol
$values
$values$NGDP_RPCH
$values$NGDP_RPCH$BOL
$values$NGDP_RPCH$BOL$`2015`
[1] 4.9

$values$NGDP_RPCH$BOL$`2016`
[1] 4.3

$values$NGDP_RPCH$BOL$`2017`
[1] 4.2

$values$NGDP_RPCH$BOL$`2018`
[1] 4.2

$values$NGDP_RPCH$BOL$`2019`
[1] 2.2

$values$NGDP_RPCH$BOL$`2020`
[1] -8.7




$api
$api$version
[1] "1"

$api$`output-method`
[1] "json"

En el caso de que se quisiera extraer información para varios países, como ser el caso de Bolivia y los Estados Unidos:

jsonlite::fromJSON(txt='https://www.imf.org/external/datamapper/api/v1/NGDP_RPCH/BOL/USA/?periods=2015,2016', simplifyVector = FALSE)
$values
$values$NGDP_RPCH
$values$NGDP_RPCH$BOL
$values$NGDP_RPCH$BOL$`2015`
[1] 4.9

$values$NGDP_RPCH$BOL$`2016`
[1] 4.3


$values$NGDP_RPCH$USA
$values$NGDP_RPCH$USA$`2015`
[1] 2.9

$values$NGDP_RPCH$USA$`2016`
[1] 1.8




$api
$api$version
[1] "1"

$api$`output-method`
[1] "json"

Para condensar todo esto en un solo lugar, podemos definir la siguiente función get_data():

get_data <- function(indicators, areas, years = NULL,
                           base = "https://www.imf.org/external/datamapper/api/v1") {

  all_out <- vector("list", length(indicators))
  names(all_out) <- indicators

  for (j in seq_along(indicators)) {
    indicator <- indicators[j]

    # 1) Llamada única por indicador con múltiples áreas
    url <- sprintf("%s/%s/%s", base, indicator, paste(areas, collapse = "/"))
    x <- jsonlite::fromJSON(url, simplifyVector = FALSE)

    out_list <- vector("list", length(areas))
    names(out_list) <- areas

    for (i in seq_along(areas)) {
      area <- areas[i]
      node <- x$values[[indicator]][[area]]

      if (is.null(node)) {
        message("No hay datos para indicator='", indicator, "' y area='", area, "'.")
        out_list[[i]] <- data.frame(code = character(), year = integer(), value = double(),
                                    indicator = character(), stringsAsFactors = FALSE)
        next
      }

      yrs_avail <- sort(as.integer(names(node)[grepl("^[0-9]{4}$", names(node))]))
      if (!length(yrs_avail)) {
        out_list[[i]] <- data.frame(code = character(), year = integer(), value = double(),
                                    indicator = character(), stringsAsFactors = FALSE)
        next
      }

      vals <- as.numeric(unlist(node[as.character(yrs_avail)], use.names = FALSE))
      df <- data.frame(code = area, year = yrs_avail, value = vals,
                       indicator = indicator, stringsAsFactors = FALSE)

      # Recorte por years (si se proporcionó), con avisos de bordes por país
      if (!is.null(years)) {
        yrs_req <- sort(unique(as.integer(years)))
        first_avail <- min(yrs_avail); last_avail <- max(yrs_avail)

        if (min(yrs_req) < first_avail)
          message("[", area, "][", indicator, "] No se devuelven datos desde ",
                  min(yrs_req), " hasta ", first_avail - 1,
                  " (primer año disponible: ", first_avail, ").")

        if (max(yrs_req) > last_avail)
          message("[", area, "][", indicator, "] No se devuelven datos desde ",
                  last_avail + 1, " hasta ", max(yrs_req),
                  " (último año disponible: ", last_avail, ").")

        df <- df[df$year %in% yrs_req, , drop = FALSE]
      }

      out_list[[i]] <- df
    }

    all_out[[j]] <- do.call(rbind, out_list)
  }

  res <- do.call(rbind, all_out)
  rownames(res) <- NULL
  res
}

La función get_data() consulta la API del IMF DataMapper para descargar en una sola llamada las series de un indicador económico (indicator) para uno o varios países (areas), devolviendo los resultados como un data.frame en formato largo con columnas de país, año, valor e indicador. Internamente, extrae del JSON los años y valores disponibles para cada país, construye un data.frame por área y, si el usuario especifica un rango de años (years), recorta la información a ese rango mostrando mensajes cuando se solicitan años fuera de los disponibles. Finalmente, combina todos los resultados en un único conjunto de datos listo para análisis o visualización.

Por ejemplo, para extraer el crecimiento del PIB real (NGDP_RPCH) para Bolivia (BOL) y Estados Unidos (USA) entre 2015 y 2020, haríamos:

get_data( 
  indicator = "NGDP_RPCH",   
  area      = c("BOL","USA"),   
  years     = 2010:2012    
)
  code year value indicator
1  BOL 2010   4.1 NGDP_RPCH
2  BOL 2011   5.2 NGDP_RPCH
3  BOL 2012   5.1 NGDP_RPCH
4  USA 2010   2.7 NGDP_RPCH
5  USA 2011   1.6 NGDP_RPCH
6  USA 2012   2.3 NGDP_RPCH

Una radiografía de países

Por ejemplo, una vez que tenemos la información, podemos hacer un análisis de la situación de determinados países. Por ejemplo, podemos ilustrar con Bolivia.

En primer lugar, cargamos las librerías necesarias:

library(tidyverse)

Luego, de la variable indicators que hemos creado anteriormente, seleccionamos los indicadores que nos interesan:

selected_ind <- c("NGDP_RPCH", # crecimiento del PIB real
                "LUR", # tasa de desempleo
                "PCPIPCH", # inflación
                "BCA_NGDPD", # cuenta corriente como % del PIB
                "GGXCNL_NGDP", # balance fiscal del gobierno general como % del PIB
                "Reserves_M" # reservas internacionales sobre importaciones
                )

Luego, seleccionamos los países que nos interesan:

areas <- c("BOL")

Finalmente, extraemos los datos para el período 2010-2023:

data <- get_data(indicators = selected_ind,
                 areas      = areas,
                 years      = 2000:2025
                 )
data <- data |> 
  left_join(indicators, by = c("indicator" = "code")) 

data |>
  slice_sample(n = 10)
   code year     value   indicator                                    label
1   BOL 2006  4.800000   NGDP_RPCH                          Real GDP growth
2   BOL 2020 -8.700000   NGDP_RPCH                          Real GDP growth
3   BOL 2002 -8.800000 GGXCNL_NGDP General government net lending/borrowing
4   BOL 2016  3.600000     PCPIPCH  Inflation rate, average consumer prices
5   BOL 2008  4.400000         LUR                        Unemployment rate
6   BOL 2002  2.500000   NGDP_RPCH                          Real GDP growth
7   BOL 2025  5.100000         LUR                        Unemployment rate
8   BOL 2014  1.700000   BCA_NGDPD  Current account balance, percent of GDP
9   BOL 2005  5.400000     PCPIPCH  Inflation rate, average consumer prices
10  BOL 2003  5.563794  Reserves_M                     Reserve/(Import/12) 

De forma gráfica:

data |>
  ggplot(aes(x = year, y = value, color = code)) +
  geom_line(size = 1.2, color ='steelblue') +
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
  facet_wrap(~ label, scales = "free_y", ncol = 2) +
  labs(title = NULL,
       x = "Año",
       y = "Valor",
       color = "País") +
  theme_bw() +
  theme(legend.position = "none")

O, por ejemplo, para el caso de España:

selected_ind <- c("NGDP_RPCH", # crecimiento del PIB real
                "LUR", # tasa de desempleo
                "PCPIPCH", # inflación
                "BCA_NGDPD", # cuenta corriente como % del PIB
                "GGXCNL_NGDP", # balance fiscal del gobierno general como % del PIB
                "GGCBP_G01_PGDP_PT" # deuda pública como % del PIB
                )

data_esp <- get_data(indicators = selected_ind,
                 areas      = 'ESP',
                 years      = 2000:2025
                 )
data_esp <- data_esp |> 
  left_join(indicators, by = c("indicator" = "code")) 

data_esp |>
  ggplot(aes(x = year, y = value, color = code)) +
  geom_line(size = 1.2, color ='steelblue') +
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
  facet_wrap(~ label, scales = "free_y", ncol = 2) +
  labs(title = NULL,
       x = "Año",
       y = "Valor",
       color = "País") +
  theme_bw() +
  theme(legend.position = "none")

Conclusiones

En esta entrada hemos visto cómo extraer datos del FMI a través de su API del Data Mapper. Hemos definido dos funciones, get_catalog() y get_data(), que facilitan la extracción de catálogos de indicadores y países, así como la obtención de datos específicos para análisis económicos. Finalmente, hemos ilustrado cómo utilizar estos datos para realizar un análisis gráfico de indicadores económicos para países como Bolivia y España. Esta metodología permite un acceso eficiente y estructurado a datos económicos internacionales, facilitando el análisis comparativo y la toma de decisiones informadas.