Extracción de datos de CEPAL en R y aplicación a la inflación en Bolivia

sept. 20, 2025·
Roger Mario López Justiniano
Roger Mario López Justiniano
· 12 min de lectura

Desde hace unos meses, la situación económica boliviana ha ido en constante deterioro: déficit fiscal sostenido, agotamiento de las reservas internacionales y consecuente ruptura del tipo de cambio fijo, etcétera. Uno de los indicadores donde se ha manifestado el problema es el de la inflación que, como se verá más adelante, ha ido incrementándose considerablemente.

Sin embargo, cuando ésta comenzó a despegar, algunos analistas indicaban que, en realidad, era un problema transitorio porque los bienes no transables, aquellos producidos localmente y que no tienen competencia internacional como los servicios o los alquileres, no estaban incrementando sus precios.

Esto me llevó a buscar algún indicador disponible para verificar esta afirmación y, afortunadamente, la CEPAL ya tenía algunas medidas listas para ser analizadas. Por si fuera poco, también se tiene una API con la cual, introduciendo el ID del indicador que se quiere analizar, se obtienen los datos automáticamente.

Entonces, el objetivo de esta entrada es doble: por un lado, mostrar cómo se pueden extraer datos de la CEPAL y, por otro, como caso práctico, analizar la evolución de la inflación en Bolivia y compararla con la de distintos países de la región.

Extracción de datos de la CEPAL

Para extraer datos de la CEPAL se puede usar la API que ellos mismos ponen a disposición. La documentación de la API está disponible en este enlace.

Primero, sin embargo, cargamos las librerías que vamos a usar desde R:

library(tidyverse)
library(readxl)

Ahora, como se puede ver en la documentación, la url para descargar los datos es: https://api-cepalstat.cepal.org/cepalstat/api/v1/indicator/{indicator_id}/data. Así, la parte {indicator_id} se debe reemplazar por el ID del indicador que se quiere analizar. Además, sobre esta, se pueden especificar distintos parámetros, como ser el lenguaje, lang, o el formato para la descarga, format. Estos parámetros se especfican al final de la url, separados por &. Por ejemplo, para descargar los datos en formato Excel y en español, se debe agregar ?format=excel&lang=es al final de la url. El listado completo de parámetros está disponible en la documentación:

¿Cómo extraemos el indicator_id? Existen distintas formas de hacerlo. La forma “manual” sería navegando por el visualizador de datos de la CEPAL, descargando en .xlsx y buscando el ID en la pestaña metadatos.

Otra forma más automática es descargar el listado completo de indicadores disponibles. Esto se puede hacer, también, haciendo un llamado a la API, pero esta vez a la url: https://api-cepalstat.cepal.org/cepalstat/api/v1/thematic-tree. Nuevamente, se pueden especificar los parámetros format y lang. Así, para descargar el listado completo de indicadores en español y en formato Excel, se debe usar la url: https://api-cepalstat.cepal.org/cepalstat/api/v1/thematic-tree?format=excel&lang=es.

En el siguiente código se muestra cómo descargar este listado y cargarlo en R:

tmp <- tempfile(fileext = ".xlsx")
download.file(
  "https://api-cepalstat.cepal.org/cepalstat/api/v1/thematic-tree?format=excel&lang=es",
  destfile = tmp, mode = "wb"
)

indicators <- read_xlsx(tmp) |> 
  filter(type == "indicator") |>
  select(id, name)

indicators |> 
  glimpse()
Rows: 1,957
Columns: 2
$ id   <dbl> 4788, 4789, 4792, 4793, 4795, 4787, 4786, 3770, 4784, 4785, 4790,…
$ name <chr> "Población total, según sexo", "Población, por grupos de edad, se…

¿Qué hace el código anterior? Primero, crea un archivo temporal para descargar el listado de indicadores. Luego, usa la función download.file para descargar el archivo desde la url especificada y guardarlo en el archivo temporal. Después, usa la función read_xlsx del paquete readxl para leer el archivo Excel y cargarlo en un data frame llamado indicators. Finalmente, filtra las filas para quedarse solo con aquellas que son de tipo “indicator” y selecciona solo las columnas id y name. La función glimpse muestra una vista rápida del data frame resultante.

Como se puede ver, hay 1957 indicadores disponibles. Por ejemplo, el indicador con ID 4788 corresponde a la “Población total, según sexo”, mientras que el indicador con ID 4789 corresponde a la “Población, por grupos de edad, según sexo”, etc.

Sobre este listado, almacenado en el data frame indicators, se pueden hacer búsquedas para encontrar los indicadores que nos interesan.

En el caso de los índices de precios:

indicators |> 
  filter(str_detect(name, "Indice de precios"))
# A tibble: 7 × 2
     id name                                                
  <dbl> <chr>                                               
1  1684 Indice de precios al consumidor, alimentos y bebidas
2  4747 Indice de precios al consumidor resto               
3   365 Indice de precios al consumidor                     
4   764 Indice de precios al consumidor subyacente          
5   762 Indice de precios al consumidor en transables       
6   763 Indice de precios al consumidor en no transables    
7   544 Indice de precios al por mayor                      

Así, nos interesan los indicadores con ID 365, 762, 763, 764, principalmente.

Por ejemplo, para descargar el índice de precios al consumidor (IPC):

tmp <- tempfile(fileext = ".xlsx")
download.file(
  "https://api-cepalstat.cepal.org/cepalstat/api/v1/indicator/365/data?format=excel&in=1&lang=en",
  destfile = tmp, mode = "wb"
)

ipc <- read_xlsx(tmp) |> 
  janitor::clean_names()

ipc |> 
  glimpse()
Rows: 16,692
Columns: 8
$ indicator        <chr> "Consumer price index", "Consumer price index", "Cons…
$ years_estandar   <chr> "1980", "1980", "1980", "1980", "1980", "1980", "1980…
$ months           <chr> "January", "January", "January", "January", "January"…
$ country_estandar <chr> "Argentina", "Bolivia (Plurinational State of)", "Bra…
$ value            <dbl> 1.19815e-07, 1.40000e-04, 3.01600e-10, 7.32000e-01, 5…
$ unit             <chr> "Index", "Index", "Index", "Index", "Index", "Index",…
$ notes_ids        <chr> "2820", "3776,8658", "2824,5933", "2826,5935", "5938,…
$ source_id        <dbl> 256, 273, 258, 259, 262, 937, 277, 265, 925, 271, 256…

De esta manera podemos descargar los datos de los distintos indicadores y analizarlos de una manera sistemática.

Inflación en Bolivia

Inflación general

Ahora, veamos cómo se ha comportado la inflación en Bolivia. Para esto, usamos el IPC que acabamos de descargar y calculamos la inflación interanual:

ipc_clean <- ipc |>
  mutate(Country = ifelse(grepl('Bolivia',country_estandar), 'Bolivia', country_estandar),
         Date_str = paste0(months, "-", years_estandar),
         Date = lubridate::my(Date_str),
         ) |>
  select(Date, Country, value) |> 
  arrange(Country, Date) |>
  group_by(Country) |>
  mutate(Inf_12m = (value/lag(value, 12) - 1) * 100) |>
  ungroup() |>
  filter(!is.na(Inf_12m))

Ahora, graficamos la inflación interanual en Bolivia:

ipc_clean |> 
  filter(Country == "Bolivia",
         Date >= as.Date("2018-01-01")
         ) |>
 ggplot(aes(x = Date)) +
  geom_line(aes(y = Inf_12m, color = "Inflación"), size = 1, color = 'red') +
  labs(title = "Inflación general interanual en Bolivia",
       x = NULL,
       y = "Inflación (%)",
       color = "",
              caption = "\nFuente: Elaboración propia en base a CEPAL."
       ) +
  theme_bw(base_family = 'Latin Modern Roman') +
  scale_x_date(date_labels = "%b-%Y", date_breaks = "3 months",
               limits = as.Date(c("2018-01-01", "2025-08-01"))
               ) +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5),
        plot.caption = element_text(hjust = 0, face = "italic"),
        #panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        legend.position = "none")

¿Cómo se compara la inflación en Bolivia con la de otros países de la región?

color <- "gray70"

ipc_clean |>
  filter(Country %in% c("Bolivia", "Paraguay", "Brazil", "Chile", "Colombia", 
                        "Mexico", "Peru", "Uruguay", "Ecuador", "Panama", 
                        "Costa Rica", "El Salvador"),
         Date >= as.Date("2018-01-01")) |>
  ggplot(aes(x = Date, y = Inf_12m, color = Country,
             alpha = ifelse(Country == "Bolivia", "Bolivia", "Other"))) +
  geom_line(size = 1) +
  labs(title = "Inflación interanual en Bolivia versus otros países de la región",
      # subtitle = "Desde enero de 2019 hasta junio de 2025",
       x = NULL,
       y = "Inflación (%)",
       color = "",
       caption = "\nFuente: Elaboración propia en base a INE.\nLos países listados son: Paraguay, Brasil, Chile, Colombia, México, Perú, Uruguay, Ecuador, Panamá, Costa Rica y El Salvador.") +
  theme_bw(base_family = "Latin Modern Roman") +
  scale_x_date(date_labels = "%b-%Y", date_breaks = "3 months",
               limits = as.Date(c("2018-01-01", "2025-08-01"))) +
  scale_color_manual(values = c("Bolivia" = "red", 
                                "Paraguay" = color, "Brazil" = color,
                                "Chile" = color, "Colombia" = color,
                                "Mexico" = color, "Peru" = color,
                                "Uruguay" = color, "Ecuador" = color,
                                "Panama" = color, "Costa Rica" = color,
                                "El Salvador" = color)) +
  scale_alpha_manual(values = c("Bolivia" = 1, "Other" = 0.4), guide = "none") +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5),
        plot.caption = element_text(hjust = 0, face = "italic"),
        #panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        legend.position = "none")

Inflación núcleo

Otro indicador interesante es la inflación núcleo, que excluye los precios de los alimentos y la energía, que suelen ser más volátiles. La CEPAL también tiene este indicador disponible (ID 764).

tmp <- tempfile(fileext = ".xlsx")
download.file(
  "https://api-cepalstat.cepal.org/cepalstat/api/v1/indicator/764/data?format=excel&in=1&lang=en",
  destfile = tmp, mode = "wb"
)

ipc_core <- read_xlsx(tmp) |> 
  janitor::clean_names()


ipc_core |>
  glimpse()
Rows: 10,553
Columns: 8
$ indicator        <chr> "Core inflation", "Core inflation", "Core inflation",…
$ years_estandar   <chr> "1990", "1991", "1992", "1993", "1994", "1995", "1996…
$ months           <chr> "January", "January", "January", "January", "January"…
$ country_estandar <chr> "Argentina", "Argentina", "Argentina", "Argentina", "…
$ value            <dbl> 0.65900, 5.77200, 10.00600, 11.15600, 11.65100, 13.38…
$ unit             <chr> "Core Inflation", "Core Inflation", "Core Inflation",…
$ notes_ids        <chr> "2820,7747,7748", "2820,7747,7748", "2820,7747,7748",…
$ source_id        <dbl> 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256…

Ahora, limpiamos los datos y calculamos la inflación interanual:

ipc_core_clean <- ipc_core |>
  mutate(Country = ifelse(grepl('Bolivia',country_estandar), 'Bolivia', country_estandar),
         Date_str = paste0(months, "-", years_estandar),
         Date = lubridate::my(Date_str),
  ) |>
  select(Date, Country, value) |>
  arrange(Country, Date) |>
  group_by(Country) |>
  mutate(Inf_12m_core = (value/lag(value, 12) -
                          1) * 100) |>
  ungroup() |>
  filter(!is.na(Inf_12m_core))

Ahora, graficamos la inflación núcleo en Bolivia:

ipc_core_clean |>
  filter(Country == "Bolivia",
         Date >= as.Date("2018-01-01")
  ) |>
  ggplot(aes(x = Date)) +
  geom_line(aes(y = Inf_12m_core, color = "Inflación"), color = "red", size = 1) +
  labs(title = "Inflación núcleo interanual en Bolivia",
       x = NULL,
       y = "Inflación (%)",
       color = "",
       caption = "\nFuente: Elaboración propia en base a CEPAL."
  ) +
  theme_bw(base_family = 'Latin Modern Roman') +
  scale_x_date(date_labels = "%b-%Y", date_breaks = "3 months"
               , limits = as.Date(c("2018-01-01", "2025-08-01"))
  ) +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5),
        plot.caption = element_text(hjust = 0, face = "italic"),
        panel.grid.minor = element_blank(),
        legend.position = "none")

¿Cómo se compara la inflación núcleo en Bolivia con la de otros países de la región?

ipc_core_clean |>
  filter(Country %in% c("Bolivia", "Paraguay", "Brazil", "Chile", "Colombia",
                        "Peru", "Uruguay", "Ecuador", "Panama",
                        "Costa Rica", "El Salvador"),
         Date >= as.Date("2018-01-01")) |>
  ggplot(aes(x = Date, y = Inf_12m_core, color = Country,
             alpha = ifelse(Country == "Bolivia", "Bolivia", "Other"))) +
  geom_line(size = 1) +
  labs(title = "Inflación núcleo interanual en Bolivia versus otros países de la región",
       x = NULL,
       y = "Inflación (%)",
       color = "",
       caption = "\nFuente: Elaboración propia en base a CEPAL.\nLos países listados son: Paraguay, Brazis, Chile, Colombia, Perú, Uruguay, Ecuador, Panamá, Costa Rica y El Salvador.") +
  theme_bw(base_family = "Latin Modern Roman") +
  scale_x_date(date_labels = "%b-%Y", date_breaks = "3 months",
               limits = as.Date(c("2018-01-01", "2025-08-01"))) +
  scale_color_manual(values = c("Bolivia" = "red",
                                "Paraguay" = color, "Brazil" = color,
                                "Chile" = color, "Colombia" = color,
                                "Mexico" = color, "Peru" = color,
                                "Uruguay" = color, "Ecuador" = color,
                                "Panama" = color, "Costa Rica" = color,
                                "El Salvador" = color)) +
  scale_alpha_manual(values = c("Bolivia" = 1, "Other" = 0.4), guide = "none") +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5),
        plot.caption = element_text(hjust = 0, face = "italic"),
        panel.grid.minor = element_blank(),
        legend.position = "none")

Inflación de transables y no transables

Finalmente, veamos la evolución de los precios de los bienes transables y no transables. La CEPAL también tiene estos indicadores disponibles (ID 762 y 763, respectivamente).

tmp <- tempfile(fileext = ".xlsx")
download.file(
  "https://api-cepalstat.cepal.org/cepalstat/api/v1/indicator/762/data?format=excel&in=1&lang=en",
  destfile = tmp, mode = "wb"
)

ipc_transable <- read_xlsx(tmp) |> 
  janitor::clean_names()

ipc_transable |>
  glimpse()
Rows: 10,753
Columns: 8
$ indicator        <chr> "Tradable consumer price index", "Tradable consumer p…
$ years_estandar   <chr> "1990", "1991", "1992", "1993", "1994", "1995", "1996…
$ months           <chr> "January", "January", "January", "January", "January"…
$ country_estandar <chr> "Argentina", "Argentina", "Argentina", "Argentina", "…
$ value            <dbl> 0.55000, 5.32400, 9.55800, 11.57400, 12.63700, 12.697…
$ unit             <chr> "Index of Transable goods", "Index of Transable goods…
$ notes_ids        <chr> "2820,7747,7748", "2820,7747,7748", "2820,7747,7748",…
$ source_id        <dbl> 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256…
tmp <- tempfile(fileext = ".xlsx")
download.file(
  "https://api-cepalstat.cepal.org/cepalstat/api/v1/indicator/763/data?format=excel&in=1&lang=en",
  destfile = tmp, mode = "wb"
)

ipc_nontransable <- read_xlsx(tmp) |> 
  janitor::clean_names()
ipc_nontransable |>
  glimpse()
Rows: 10,755
Columns: 8
$ indicator        <chr> "Non-tradable consumer price index", "Non-tradable co…
$ years_estandar   <chr> "1990", "1991", "1992", "1993", "1994", "1995", "1996…
$ months           <chr> "January", "January", "January", "January", "January"…
$ country_estandar <chr> "Argentina", "Argentina", "Argentina", "Argentina", "…
$ value            <dbl> 0.57400, 5.61200, 9.48800, 11.03800, 11.91800, 12.732…
$ unit             <chr> "Index of non-tradable goods and services", "Index of…
$ notes_ids        <chr> "2820,7747,7748", "2820,7747,7748", "2820,7747,7748",…
$ source_id        <dbl> 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256…

Ahora, limpiamos los datos y calculamos la inflación interanual:

ipc_transable_clean <- ipc_transable |>
  mutate(Country = ifelse(grepl('Bolivia',country_estandar), 'Bolivia', country_estandar),
         Date_str = paste0(months, "-", years_estandar),
         Date = lubridate::my(Date_str),
  ) |>
  select(Date, Country, value) |>
  arrange(Country, Date) |>
  group_by(Country) |>
  mutate(Inf_12m_transable = (value/lag(value, 12) -1) * 100) |>
  ungroup() |>
  filter(!is.na(Inf_12m_transable))

ipc_nontransable_clean <- ipc_nontransable |>
  mutate(Country = ifelse(grepl('Bolivia',country_estandar), 'Bolivia', country_estandar),
         Date_str = paste0(months, "-", years_estandar),
         Date = lubridate::my(Date_str),
  ) |>
  select(Date, Country, value) |>
  arrange(Country, Date) |>
  group_by(Country) |>
  mutate(Inf_12m_nontransable = (value/lag(value, 12)-1) * 100) |>
  ungroup() |>
  filter(!is.na(Inf_12m_nontransable))
  
ipc_both <- ipc_transable_clean |>
  select(Date, Country, Inf_12m_transable) |>
  left_join(ipc_nontransable_clean |>
              select(Date, Country, Inf_12m_nontransable),
            by = c("Date", "Country"))

Ahora, graficamos la inflación de bienes transables y no transables en Bolivia:

ipc_both |>
  filter(Country == "Bolivia",
         Date >= as.Date("2018-01-01")
  ) |>
  pivot_longer(cols = c(Inf_12m_transable, Inf_12m_nontransable),
               names_to = "Type", values_to = "Inflation") |>
  mutate(Type = recode(Type,
                       Inf_12m_transable = "Bienes transables",
                       Inf_12m_nontransable = "Bienes no transables")) |>
  ggplot(aes(x = Date, y = Inflation, color = Type)) +
  geom_line(size = 1) +
  scale_color_manual(values = c("Bienes transables" = "gray80", "Bienes no transables" = "red")) +
  labs(title = "Inflación interanual en Bolivia: bienes transables y no transables",
       x = NULL,
       y = "Inflación (%)",
       color = "",
       caption = "\nFuente: Elaboración propia en base a CEPAL."
  ) +
  theme_bw(base_family = 'Latin Modern Roman') +
  scale_x_date(date_labels = "%b-%Y", date_breaks = "3 months" , limits = as.Date(c("2018-01-01", "2025-08-01"))
  ) +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5),
        plot.caption = element_text(hjust = 0, face = "italic"),
        panel.grid.minor = element_blank(),
        legend.position = "bottom")

Todas las inflaciones juntas

Finalmente, veamos todas las inflaciones juntas:

ipc_clean |>
  filter(Country == "Bolivia",
         Date >= as.Date("2018-01-01")
  ) |>
  select(Date, Inf_12m) |>
  left_join(ipc_core_clean |>
              filter(Country == "Bolivia") |>
              select(Date, Inf_12m_core),
            by = "Date") |>
  left_join(ipc_both |>
              filter(Country == "Bolivia") |>
              select(Date, Inf_12m_transable, Inf_12m_nontransable),
            by = "Date") |>
  pivot_longer(cols = c(Inf_12m, Inf_12m_core, Inf_12m_transable, Inf_12m_nontransable),
               names_to = "Type", values_to = "Inflation") |>
  mutate(Type = recode(Type,
                       Inf_12m = "Inflación general",
                       Inf_12m_core = "Inflación núcleo",
                       Inf_12m_transable = "Inflación transables",
                       Inf_12m_nontransable = "Inflación no transables")) |>
  ggplot(aes(x = Date, y = Inflation, color = Type)) +
  geom_line(size = 1, alpha = 1) +
  scale_color_manual(values = c("Inflación general" = "#4682B4",
                                "Inflación núcleo" = "#E74C3C",
                                "Inflación transables" = "#F1C40F",
                                "Inflación no transables" = "#2ECC71")) +
  labs(title = "Inflación interanual en Bolivia: todos los indicadores",
       x = NULL,
       y = "Inflación (%)",
       color = "",
       caption = "\nFuente: Elaboración propia en base a CEPAL.") +
  theme_bw(base_family = 'Latin Modern Roman') +
  scale_x_date(date_labels = "%b-%Y", date_breaks = "3 months" , limits = as.Date(c("2018-01-01", "2025-08-01"))
  ) +
  scale_y_continuous(limits = c(-5, 35), breaks = seq(-5,35,5)  ) +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5),
        plot.caption = element_text(hjust = 0, face = "italic"),
        panel.grid.minor = element_blank(),
        legend.position = "bottom")

Así, se puede observar que para agosto de 2025 la inflación iba desde 16.05% en el caso de la inflación para bienes no transables hasta 30.43% para bienes transables.

Conclusiones

En esta entrada se mostró cómo extraer datos de la CEPAL usando su API y, como caso práctico, se analizó la evolución de la inflación en Bolivia y su comparación con otros países de la región. Se observó que la inflación en Bolivia ha sido significativamente más alta que en otros países de la región, y que tanto los bienes transables como los no transables han experimentado aumentos de precios, aunque los no transables han tardado un poco más en elevarse.