Construcción base datos comercio e inversion en Mexico

Jorge Cornick, 11 de agosto 2025

Introducción

Propósitos del reporte

Este reporte documenta el proceso de creación de la base de datos sobre comercio exterior e inversión extranjera directa que será utilizado en el “Flagship” sobre NS en México dirigido por Ernesto Stein.

Esta documentación permitirá a futuros usuarios:

  • Verificar el origen y definición de los datos
  • Replicar y en su caso actualizar la base de datos
  • Entender los cambios en la organización de los datos1
  • Entender las transformaciones de las variables originales con propósitos de análisis

Con el fin de facilitar el trabajo de futuros usuarios que apenas se estén iniciando en el uso de R, se explican con cierto detalle algunas herramientas y procesos la primera vez que son utilizados en este documento.

Tareas preliminares

El primer paso necesario para extraer y formatear la información que se almacenará en nuestra base de datos consiste en cargar los “paquetes” de R necesarios para:

  • Interactuar con bases de datos en línea (httr)
  • Extraer datos y metadatos almacenados en formato JSON (jsonlite)
  • Trabajar con variables categóricas o factores (forcats)
  • Assignar clase “Date” a distintas variables (zoo)
  • Trabajar con datos en formato tidy (tidyverse)
library(httr)
library(jsonlite)
library(forcats)
library(zoo)
library(tidyverse) 
library(readxl)

Bases de datos de comercio exterior

Exportaciones e importaciones totales por país de destino u origen

Los datos de comercio exterior han sido descargados del portal DataMexico. Concretamente, se ha generado la siguiente consulta:

Las API correspondientes a esta consulta se despliegan haciendo “click” en API (ver imagen anterior, arriba a la derecha) y el resultado es el siguiente:

El primer paso consiste en convertir el API en un objeto con el que R pueda trabajar:

api_url <- "https://www.economia.gob.mx/apidatamexico/tesseract/data.jsonrecords?cube=inegi_foreign_trade_country&drilldowns=Year%2CFlow%2CCountry&locale=es&measures=Trade+Value"

Y ahora usamos ese objeto para descargar la información que requerimos

response <- GET(api_url)

Cuando se usa httr, “response” es un una clase de objeto que contiene información sobre la respuesta a GET, como “status” (200 para OK, 404 para objeto no encontrado)“,”headers” (tipo de objeto, servidor,…),“Content” (los datos, en formato JSON, XML u otros).

Procedemos, entonces, a verificar el éxito de la operación:

status_code(response)
[1] 200

Seguidamente convertimos la información a un archivo de texto plano

data_json <- content(response, "text", encoding = "UTF-8")

Ahora creamos un objeto tipo “list”, que contiene tanto los datos propiamente dichos como información sobre esos datos (metadata)

data_list <- fromJSON(data_json)

Procedemos ahora a crear un data frame con los datos contenidos en data_list. Usamos el nombre df_raw para conservar toda la informacion inicialmente descargada. Es posible que a lo largo del proceso de análisis de la información decidamos modificar nuestra base de datos de distintas maneras, no todos previstas desde el inicio. Para evitar tener que descargar de nuevo los datos desde Data Mexico, guardaremos ese archivo inicial y no lo modificaremos en ningún momento

dfXM_raw <- as.data.frame(data_list$data)
save(dfXM_raw, file = "../Data/dfXM_raw")

Procedemos a verificar las variables en df y la clase de objetos que corresponde a cada una de ellas:

str(dfXM_raw)
'data.frame':   15510 obs. of  6 variables:
 $ Year       : int  1993 1993 1993 1993 1993 1993 1993 1993 1993 1993 ...
 $ Flow ID    : int  1 1 1 1 1 1 1 1 1 1 ...
 $ Flow       : chr  "Importaciones" "Importaciones" "Importaciones" "Importaciones" ...
 $ Country ID : chr  "abw" "afg" "ago" "aia" ...
 $ Country    : chr  "Aruba" "Afganistán" "Angola" "Anguilla" ...
 $ Trade Value: num  0 396000 110000 0 82000 ...

Esta base de datos contiene información para más de 200 países. Definimos un vector con los seis principales socios comerciales.

p_clave <- c("Alemania","Brasil","Canadá","China","Corea del Sur","Estados Unidos")

Seguidamente seleccionamos las variables que nos interesan, les ponemos nombres en castellano (sin acentos) y le damos formato tidy a los datos.

Los nombres de algunso países tienen más de dos palabras: los transformamos en nombres de uan sola palabra, para facilitar la codificación posterior.

Además, creamos una categoría llamada “Otros”, en las que sumamos todas las exportaciones e importaciones a países que no forman parte de los seis principales socios comerciales.

Nótese que re escalamos exportaciones e importaciones, que están en dólares en la base de datos original, y que aquí convertimos en millones de dólares

p_clave <- c("Alemania","Brasil","Canadá","China","CoreaS","USA")

df <- dfXM_raw |> select(Year, Flow, Country,`Trade Value`)
df <- df |> 
  rename(
    Año = Year,
    Flujo = Flow,
    Pais = Country,
    Valor = `Trade Value`) |>
  mutate(
    Flujo = as.factor(Flujo),
    País = as.factor(Pais),
    Pais = fct_recode(Pais,
                      "USA" = "Estados Unidos",
                      "CoreaS" = "Corea del Sur")
      ) |> 
  pivot_wider(
      names_from = Flujo, values_from = Valor
      ) |> 
  mutate(Importaciones = Importaciones/1000000,
             Exportaciones = Exportaciones/1000000) |> 
  mutate(Pais = fct_other(Pais, keep = p_clave, other_level = "Otros")) |>
  group_by(Año, Pais) |>
  summarise(
    Importaciones = sum(Importaciones),
    Exportaciones = sum(Exportaciones),
    .groups = "drop"
  )

Verifiquemos una vez más nombres y clases

str(df)
tibble [231 × 4] (S3: tbl_df/tbl/data.frame)
 $ Año          : int [1:231] 1993 1993 1993 1993 1993 1993 1993 1994 1994 1994 ...
 $ Pais         : Factor w/ 7 levels "Alemania","Brasil",..: 1 2 3 4 5 6 7 1 2 3 ...
 $ Importaciones: num [1:231] 2852 1201 1175 386 837 ...
 $ Exportaciones: num [1:231] 430.2 293 1562.9 44.8 27.1 ...

Con esto, ya estamos en condiciones de crear nuestro primer data frame en formato R

MexXMtotpais <- df

Notese la especificación del “path” para guardar el archivo. Este documento está escrito en Quarto, en un folder para todos los archivos cuarto. La estructura de mi directorio de trabajo es la siguiente:

Para guardar el documento en la carpeta correcta, debemos indicarle a Quarto que suba un nivel dentro de la estructura del directorio, es decir, que se coloque en el directorio de trabajo y no en la carpeta correspondiente a Quarto, y luego busque la carpeta Data y guarde allí la información. Esta misma información deberá tenerse en cuenta al cargar, desde Quarto, bases de datos almacenadas en la carpeta Data.

save(MexXMtotpais, file = "../Data/MexXMtotpais.RData")

Exportaciones e importaciones por producto

La información de exportaciones por producto en DataMexico se presenta en dos niveles de desagregación: “Capítulos” que incluye un total de 20 categorías, y códigos HS a 2 dígitos, que corresponde a 97 categorías distintas 2.

En esta primera iteración se han descargado los datos correspondientes a los 20 “Capítulos”, pero posteriormente se podría descargar información más granular para los productos de mayor interés desde la perspectiva del NS.

El proceso de extracción de los datos es esencialmente el mismo que se utilizó en la sección anterior, por lo que en esta ocasión se prescinde de explicaciones paso a paso.

Primer paso: descarga y extracción de los datos. Nótese que se asignan a nuevos objetos nombres previamente utilizados. Como se trata de objetos temporales, que se utilizan únicamente como pasos intermedios antes de la creación del data frame en formato R, esto no es un problema.

api_url <- "https://www.economia.gob.mx/apidatamexico/tesseract/data.jsonrecords?cube=inegi_foreign_trade_product&drilldowns=Quarter%2CChapter+2+Digit%2CFlow&locale=es&measures=Trade+Value"
response <- GET(api_url)
status_code(response)
data_json <- content(response, "text", encoding = "UTF-8")
data_list <- fromJSON(data_json)
df <- as.data.frame(data_list$data)
str(df)

Al igual que en el caso anterior, eliminaremos las columnas que corresponden a ID de las variables, dejando únicamente las columnas con sus nombre. Aunque se especificó en la búsqueda que los nombres de las variables deberían expresarse en castellano, aparecen en inglés, por lo que será necesario traducirlos, y finalmente, la columna “Flujo” se dividirá en dos columnas separadas, una para “Exportaciones” y otra para “Importaciones”

df <- df |> select(!ends_with("ID")) |> 
  rename(Trimestre = Quarter,
         Flujo = Flow,
         Capítulo = `Chapter 2 Digit`,
         Valor = `Trade Value`)
str(df)
'data.frame':   4940 obs. of  4 variables:
 $ Trimestre: chr  "1993-Q1" "1993-Q1" "1993-Q1" "1993-Q1" ...
 $ Capítulo : chr  "Los Productos de Origen Animal" "Los Productos de Origen Animal" "Productos del Reino Vegetal" "Productos del Reino Vegetal" ...
 $ Flujo    : chr  "Importaciones" "Exportaciones" "Importaciones" "Exportaciones" ...
 $ Valor    : num  3.66e+08 2.00e+08 5.30e+08 8.84e+08 1.08e+08 ...

Queremos convertir Trimestre es una variable de fecha en vez de una secuencia de carateres

df$Trimestre <- as.yearqtr(df$Trimestre,format = "%Y-Q%q")

Separamos Exportaciones e Importaciones y re escalamos

df <- df |> pivot_wider(
  names_from = Flujo, values_from = Valor) |> 
  mutate(Importaciones = Importaciones/1000000,
         Exportaciones = Exportaciones/1000000)

Y convertimos Capítulo a factor

df$Capítulo <- as.factor(df$Capítulo)

Pero aún nos queda una tarea pendiente. Los nombres de los capítulos son muy extensos y compuestos de varias palabras, lo que resulta inconventiente para el trabajo posterior, así que recodificamos los niveles del factor Capítulo:

df <- df |> 
  mutate(Capítulo = fct_recode(Capítulo,
                               "Animales" = "Los Productos de Origen Animal",
                               "Vegetales" = "Productos del Reino Vegetal",
                               "Animal_Veg" = "Animales y Vegetales Bi-Productos",
                               "Alimentos" = "Los Productos Alimenticios",
                               "Minerales" = "Productos Minerales",
                               "Quimicos" = "Productos Químicos",
                               "Plásticos" = "Plásticos y Cauchos",
                               "Pieles" = "Pieles de Animales",
                               "Madera" = "Productos de Madera",
                               "Papel" = "Artículos de Papel",
                               "CalzSomb" = "Calzado, y Sombreros",
                               "Piedra" = "Piedra y Cristal",
                               "MPreciosos" = "Metales Preciosos",
                               "Otros" = "Diverso"))

Verificamos una vez más que el data frame tenga la estructura que deseamos:

str(df)
tibble [2,470 × 4] (S3: tbl_df/tbl/data.frame)
 $ Trimestre    : 'yearqtr' num [1:2470] 1993 Q1 1993 Q1 1993 Q1 1993 Q1 ...
 $ Capítulo     : Factor w/ 19 levels "Animal_Veg","Papel",..: 7 14 1 6 15 16 12 11 13 2 ...
 $ Importaciones: num [1:2470] 366 530 108 310 516 ...
 $ Exportaciones: num [1:2470] 200.12 883.67 3.45 198.75 1922.84 ...

Con lo cual podemos salvar nuestra nueva base de datos

MexXMproducto <- df
save(MexXMproducto, file = "../Data/MexXMproducto.RData")

Exportaciones e importaciones por estado

La información de exportaciones e importaciones por estado está disponible de modo agregado, o bien desagregada a 2 o 4 dígitos HS y con periodicidad anual, trimestral o mensual. En esta primera consulta se descargan datos anuales agregados.

Las transacciones se pueden desagregar por producto y por destino u origen, y existe la posibilidad de aplicar filtros. Así, por ejemplo, después de analizar los datos agregados de forma anual, podría seleccionarse una o varias entidades federativas y desagregar sus exportaciones por producto y destino.

Una vez discutidas las primeras visualizaciones, y a criterio del director del Proyecto, se pueden generar datos más desagregados según resulte conveniente.

Se procede con la extracción en un solo bloque de código, cuyos componentes ya antes fueron explicados paso a paso

api_url <- "https://www.economia.gob.mx/apidatamexico/tesseract/data.jsonrecords?cube=economy_foreign_trade_ent&drilldowns=Year%2CState%2CFlow&limit=50&locale=es&measures=Trade+Value"
response <- GET(api_url)
status_code(response)
[1] 200
data_json <- content(response, "text", encoding = "UTF-8")
data_list <- fromJSON(data_json)
df <- as.data.frame(data_list$data)
str(df)
'data.frame':   50 obs. of  6 variables:
 $ Year       : int  2006 2006 2006 2006 2006 2006 2006 2006 2006 2006 ...
 $ State ID   : int  1 1 2 2 3 3 4 4 5 5 ...
 $ State      : chr  "Aguascalientes" "Aguascalientes" "Baja California" "Baja California" ...
 $ Flow ID    : int  1 2 1 2 1 2 1 2 1 2 ...
 $ Flow       : chr  "Compras internacionales" "Ventas internacionales" "Compras internacionales" "Ventas internacionales" ...
 $ Trade Value: num  4.67e+09 3.20e+09 6.84e+10 7.52e+10 3.28e+08 ...

Y ahora procedemos a organizar los datos en formato tidy, asignar nombres en castellano, asignar las “clases” apropiadas a cada variable y reescalar algunas variables, exactamente igual que lo hicimos en los casos anteriores

df <- df |> select(!ends_with("ID")) |> 
  pivot_wider(names_from = Flow, values_from = `Trade Value`) |> 
  rename(Año = Year,
         Estado = State,
         Exportaciones = `Ventas internacionales`,
         Importaciones = `Compras internacionales`) |>
  mutate(Exportaciones = Exportaciones/1000000,
         Importaciones = Importaciones/1000000,
         Estado = as.factor(Estado))
str(df)
tibble [25 × 4] (S3: tbl_df/tbl/data.frame)
 $ Año          : int [1:25] 2006 2006 2006 2006 2006 2006 2006 2006 2006 2006 ...
 $ Estado       : Factor w/ 25 levels "Aguascalientes",..: 1 2 3 4 8 9 5 6 7 10 ...
 $ Importaciones: num [1:25] 4674 68414 328 518 21403 ...
 $ Exportaciones: num [1:25] 3204 75202 391 574 23173 ...

Finalmente, guardamos la base de datos en formato R

XMEstados <- df
save(XMEstados, file = "../Data/XMEstados.RData")

Exportaciones a USA por producto (20 capitulos)

Descarga

api_url <- "https://www.economia.gob.mx/apidatamexico/tesseract/data.jsonrecords?Country=usa&cube=economy_foreign_trade_nat&drilldowns=Date+Year%2CCountry%2CChapter+2+Digit&locale=es&measures=Trade+Value"
response <- GET(api_url)
status_code(response)
[1] 200
data_json <- content(response, "text", encoding = "UTF-8")
data_list <- fromJSON(data_json)
df <- as.data.frame(data_list$data)
str(df)
'data.frame':   440 obs. of  6 variables:
 $ Date Year         : int  0 0 0 0 0 0 0 0 0 0 ...
 $ Country ID        : chr  "usa" "usa" "usa" "usa" ...
 $ Country           : chr  "Estados Unidos" "Estados Unidos" "Estados Unidos" "Estados Unidos" ...
 $ Chapter 2 Digit ID: int  1 2 3 4 5 6 7 8 9 10 ...
 $ Chapter 2 Digit   : chr  "Los Productos de Origen Animal" "Productos del Reino Vegetal" "Animales y Vegetales Bi-Productos" "Los Productos Alimenticios" ...
 $ Trade Value       : num  1.36e+11 3.95e+11 1.68e+10 2.98e+11 9.49e+11 ...

Ajustes

df <- df |> select(!ends_with("ID")) |> 
  rename(Capítulo = `Chapter 2 Digit`) |> 
  mutate(Capítulo = as.factor(Capítulo)) 
levels(df$Capítulo)  
 [1] "Animales y Vegetales Bi-Productos" "Armas"                            
 [3] "Arte y Antigüedades"               "Artículos de Papel"               
 [5] "Calzado, y Sombreros"              "Diverso"                          
 [7] "Instrumentos"                      "Los Productos Alimenticios"       
 [9] "Los Productos de Origen Animal"    "Máquinas"                         
[11] "Metales Preciosos"                 "No Clasificados"                  
[13] "Piedra y Cristal"                  "Pieles de Animales"               
[15] "Plásticos y Cauchos"               "Productos de Madera"              
[17] "Productos del Reino Vegetal"       "Productos Minerales"              
[19] "Productos Químicos"                "Rieles"                           
[21] "Textiles"                          "Transporte"                       

Como se puede ver arriba, los nombres de los capítulos son muy extensos y compuestos de varias palabras, así que, tal y como lo hicimos antes en una situación similar, los recodificamos

df <- df |> mutate(Capítulo = fct_recode(Capítulo,
                               "Animales" = "Los Productos de Origen Animal",
                               "Vegetales" = "Productos del Reino Vegetal",
                               "Animal_Veg" = "Animales y Vegetales Bi-Productos",
                               "Alimentos" = "Los Productos Alimenticios",
                               "Minerales" = "Productos Minerales",
                               "Quimicos" = "Productos Químicos",
                               "Plásticos" = "Plásticos y Cauchos",
                               "Pieles" = "Pieles de Animales",
                               "Madera" = "Productos de Madera",
                               "Papel" = "Artículos de Papel",
                               "CalzSomb" = "Calzado, y Sombreros",
                               "Piedra" = "Piedra y Cristal",
                               "MPreciosos" = "Metales Preciosos",
                               "Arte" = "Arte y Antigüedades",
                               "Otros" = "No Clasificados"))
    
levels(df$Capítulo)
 [1] "Animal_Veg"   "Armas"        "Arte"         "Papel"        "CalzSomb"    
 [6] "Diverso"      "Instrumentos" "Alimentos"    "Animales"     "Máquinas"    
[11] "MPreciosos"   "Otros"        "Piedra"       "Pieles"       "Plásticos"   
[16] "Madera"       "Vegetales"    "Minerales"    "Quimicos"     "Rieles"      
[21] "Textiles"     "Transporte"  

Almacenamiento

XUSACap <- df
save(XUSACap, file = "../Data/XUSACap.RData")

Bases de datos IED

IED por tipo de inversión

Descarga

api_url <- "https://www.economia.gob.mx/apidatamexico/tesseract/data.jsonrecords?cube=fdi_year_investment_industry&drilldowns=Year%2CInvestment+Type&measures=Investment"
response <- GET(api_url)
status_code(response)
[1] 200
data_json <- content(response, "text", encoding = "UTF-8")
data_list <- fromJSON(data_json)
df <- as.data.frame(data_list$data)
str(df)
'data.frame':   78 obs. of  4 variables:
 $ Year              : int  1999 1999 1999 2000 2000 2000 2001 2001 2001 2002 ...
 $ Investment Type ID: int  1 2 3 1 2 3 1 2 3 1 ...
 $ Investment Type   : chr  "Accounts between Companies" "New Investments" "Reinvestment of Profits" "Accounts between Companies" ...
 $ Investment        : num  13824 19724 6972 16935 26009 ...

Ajustes

df <- df |> select(!ends_with("ID")) |> 
  pivot_wider(names_from = `Investment Type`, values_from = Investment) |> 
  rename(Año = Year,
         CtasInternas = `Accounts between Companies`,
         NuevaInversión = `New Investments`,
         Reinversión = `Reinvestment of Profits`)  
str(df)  
tibble [26 × 4] (S3: tbl_df/tbl/data.frame)
 $ Año           : int [1:26] 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 ...
 $ CtasInternas  : num [1:26] 13824 16935 9175 17405 20811 ...
 $ NuevaInversión: num [1:26] 19724 26009 69266 46903 26585 ...
 $ Reinversión   : num [1:26] 6972 11032 11464 7440 6451 ...

Almacenamiento

IEDtipo <- df
save(IEDtipo, file = "../Data/IEDtipo.RData")

IED por país de origen

Descarga

api_url <- "https://www.economia.gob.mx/apidatamexico/tesseract/data.jsonrecords?cube=fdi_10_year_country&drilldowns=Year%2CCountry&measures=Investment"
response <- GET(api_url)
status_code(response)
[1] 200
data_json <- content(response, "text", encoding = "UTF-8")
data_list <- fromJSON(data_json)
df <- as.data.frame(data_list$data)
str(df)
'data.frame':   1191 obs. of  4 variables:
 $ Year      : int  1999 1999 1999 1999 1999 1999 1999 1999 1999 1999 ...
 $ Country ID: chr  "arg" "aus" "aut" "bel" ...
 $ Country   : chr  "Argentina" "Australia" "Austria" "Belgium" ...
 $ Investment: num  3.54 1.32 6.2 128.31 17.63 ...

Ajustes

df <- df |> select(!ends_with("ID")) |> 
  rename(Año = Year,
         País = Country,
         Inversion = Investment) |> 
  mutate(País = as.factor(País))
str(df)  
'data.frame':   1191 obs. of  3 variables:
 $ Año      : int  1999 1999 1999 1999 1999 1999 1999 1999 1999 1999 ...
 $ País     : Factor w/ 50 levels "Argentina","Australia",..: 1 2 3 4 6 7 45 8 9 10 ...
 $ Inversion: num  3.54 1.32 6.2 128.31 17.63 ...

Almacenamiento

IEDPais <- df
save(IEDPais, file = "../Data/IEDPais.RData")

IED por sector (2 dígitos)

En esta descarga inicial la información por sector se desagrega a 2 dígitos, pero la información también está disponible a 3 y 4 dígitos.

Descarga

api_url <- "https://www.economia.gob.mx/apidatamexico/tesseract/data.jsonrecords?cube=fdi_year_state_industry&drilldowns=Nation%2CSector%2CYear&measures=Investment"
response <- GET(api_url)
status_code(response)
[1] 200
data_json <- content(response, "text", encoding = "UTF-8")
data_list <- fromJSON(data_json)
df <- as.data.frame(data_list$data)
str(df)
'data.frame':   468 obs. of  6 variables:
 $ Nation ID : chr  "mex" "mex" "mex" "mex" ...
 $ Nation    : chr  "México" "México" "México" "México" ...
 $ Sector ID : chr  "11" "11" "11" "11" ...
 $ Sector    : chr  "Agriculture, Animal Breeding and Production, Forestry, Fishing and Hunting" "Agriculture, Animal Breeding and Production, Forestry, Fishing and Hunting" "Agriculture, Animal Breeding and Production, Forestry, Fishing and Hunting" "Agriculture, Animal Breeding and Production, Forestry, Fishing and Hunting" ...
 $ Year      : int  1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 ...
 $ Investment: num  80.15 89.31 77.83 19.83 2.75 ...

Ajustes

df <- df |> select(!ends_with("ID")) |> 
  rename(Año = Year,
         Nacion = Nation)|> 
  mutate(Nacion = as.factor(Nacion),
         Sector = as.factor(Sector))
str(df) 
'data.frame':   468 obs. of  4 variables:
 $ Nacion    : Factor w/ 1 level "México": 1 1 1 1 1 1 1 1 1 1 ...
 $ Sector    : Factor w/ 19 levels "Agriculture, Animal Breeding and Production, Forestry, Fishing and Hunting",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Año       : int  1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 ...
 $ Investment: num  80.15 89.31 77.83 19.83 2.75 ...

Almacenamiento

IEDPaisSector <- df
save(IEDPaisSector,file = "../Data/IEDPaisSector.RData")

IED por sector y tipo de inversión

Descarga

api_url <- "https://www.economia.gob.mx/apidatamexico/tesseract/data.jsonrecords?cube=fdi_year_investment_industry&drilldowns=Year%2CInvestment+Type%2CSector&locale=es&measures=Investment"
response <- GET(api_url)
status_code(response)
[1] 200
data_json <- content(response, "text", encoding = "UTF-8")
data_list <- fromJSON(data_json)
df <- as.data.frame(data_list$data)
str(df)
'data.frame':   1448 obs. of  6 variables:
 $ Year              : int  1999 1999 1999 1999 1999 1999 1999 1999 1999 1999 ...
 $ Investment Type ID: int  1 1 1 1 1 1 1 1 1 1 ...
 $ Investment Type   : chr  "Cuentas entre Compañías" "Cuentas entre Compañías" "Cuentas entre Compañías" "Cuentas entre Compañías" ...
 $ Sector ID         : chr  "11" "21" "22" "23" ...
 $ Sector            : chr  "Agricultura, Cría y Explotación de Animales, Aprovechamiento Forestal, Pesca y Caza" "Minería" "Generación, Transmisión, Distribución y Comercialización de Energía Eléctrica, Suministro de Agua y de Gas Natu"| __truncated__ "Construcción" ...
 $ Investment        : num  2.301 35.757 0.642 37.517 3901.945 ...

Ajustes

df <- df |> select(!ends_with("ID")) |> 
  rename(Año = Year,
         Inversión = Investment,
         TipoIED = `Investment Type`) |> 
  pivot_wider(names_from = TipoIED, values_from = Inversión) |> 
  mutate(Sector = as.factor(Sector))
str(df) 
tibble [520 × 5] (S3: tbl_df/tbl/data.frame)
 $ Año                      : int [1:520] 1999 1999 1999 1999 1999 1999 1999 1999 1999 1999 ...
 $ Sector                   : Factor w/ 20 levels "Actividades Legislativas, Gubernamentales, de Impartición de Justicia y de Organismos Internacionales y Extraterritoriales",..: 2 10 7 5 8 3 4 20 9 17 ...
 $ Cuentas entre Compañías  : num [1:520] 2.301 35.757 0.642 37.517 3901.945 ...
 $ Nuevas Inversiones       : num [1:520] 80.3 211 273.9 67.6 3176.1 ...
 $ Reinversión de Utilidades: num [1:520] NA 36.8 0 51.3 1948.4 ...

Almacenamiento

IEDTipoSector <- df
save(IEDTipoSector, file = "../Data/IEDTipoSector.RData")

Bases de datos empleo IMMEX

# --- Use the path to your newly saved Excel file ---
file_path <- "../Excel/IMMEX_2.xlsx"

# --- 1. Read the ENTIRE sheet into a raw data frame ---
# We read it without any headers for now.
raw_sheet <- suppressMessages(read_excel(file_path, col_names = FALSE, na = c("-", "n.a.")))

# supressMessages necesario para evitar que se imprima a pantalla información innecesaria

# --- 2. Manually extract the header rows and create clean names ---
# The first row contains the years
years <- raw_sheet |> slice(1) |> unlist(use.names = FALSE)
# The second row contains the months
months <- raw_sheet |> slice(2) |> unlist(use.names = FALSE)

# Helper function to fill the merged year cells forward
fill_forward <- function(vec) {
  for (i in 2:length(vec)) {
    if (is.na(vec[i])) vec[i] <- vec[i-1]
  }
  return(vec)
}

# Create the final, unique column names (e.g., "2007_Enero")
clean_headers <- c(
  "Variable", 
  "Entidad", 
  paste(fill_forward(years[3:length(years)]), months[3:length(months)], sep = "_")
)

# --- 3. Extract the data body and assign the clean names ---
# The actual data starts on row 3. We select from row 3 to the end.
data_body <- raw_sheet |> slice(3:n())

# Now, we assign our clean headers to this data body
names(data_body) <- clean_headers


# --- 4. Tidy the data (This part of the pipeline is the same) ---
tidy_IMMEX <- data_body |>
  fill(Variable, .direction = "down") |>
  
  pivot_longer(
    cols = -c(Variable, Entidad),
    names_to = "Period",
    values_to = "Value"
  ) |>
  
  separate(Period, into = c("Year", "Month"), sep = "_", convert = TRUE) |>
  
  mutate(Value = as.numeric(Value)) |>
  
  # I noticed in your last screenshot that the "-" for missing values was gone,
  # so I've removed the na_if() step as it might no longer be necessary.
  # If you see errors again, we can add it back.
  
  filter(!is.na(Value))


# --- Display a glimpse of the result ---
#glimpse(tidy_IMMEX)
save(tidy_IMMEX, file = "../Data/tidy_IMMEX.RData")

Notas

  1. Específicamente: las bases de datos se organizan en formato “tidy”, para poder utilizar las herramientas del paquete “tidyverse”. En este formato, cada fila corresponde a una observación y cada columna a una variable. Esto contrasta con formatos “anchos” en los que, por ejemplo, las fechas se colocan en una fila en la parte superior y los valores de otras variables, como por ejemplo el PIB, en filas subsiguientes. En este caso, cada celda representa dos variables: un año determinado, y el PIB correspondiente a cada año. En formato tidy, el año y el PIB se colocan, cada uno, en celdas separadas.↩︎

  2. Ver https://www.wcoomd.org/en/topics/nomenclature/instrument-and-tools/hs-nomenclature-2022-edition/hs-nomenclature-2022-edition.aspx↩︎