Construcción base datos comercio e inversion en Mexico

Jorge Cornick, 11 de agosto 2025

library(httr)
library(jsonlite)
library(forcats)
library(zoo)
library(tidyverse) 
library(readxl)
library(here)
library(kableExtra)
library(janitor)

Bases de datos de comercio exterior

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

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"
response <- GET(api_url)
data_json <- content(response, "text", encoding = "UTF-8")
data_list <- fromJSON(data_json)
source <- data_list |>
  pluck("source") |>       # <-- This pulls the 'source' data frame out of the list
  unnest_wider(annotations) # Now unnest_wider gets the data frame it needs

# View the result
t(source)
            [,1]                                           
name        "inegi_foreign_trade_country"                  
measures    "Trade Value"                                  
source_link "https://www.inegi.org.mx/sistemas/bie/"       
table_en    "Foreign Trade (INEGI) by Country"             
topic_en    "Foreign Trade"                                
topic_es    "Comercio exterior"                            
subtopic    "Hidden"                                       
table_es    "Comercio exterior (INEGI) por países"         
source_name "Instituto Nacional de Estadística y Geografía"

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.RData")

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 ...

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

df1 <- dfXM_raw |> select(Year, Flow, Country,`Trade Value`)
df1 <- df1 |> 
  rename(
    Año = Year,
    Flujo = Flow,
    Pais = Country,
    Valor = `Trade Value`) |>
  mutate(
    Flujo = as.factor(Flujo),
    País = as.factor(Pais)
      ) |> 
  mutate(
    Pais = fct_relabel(Pais, \(level) str_replace_all(level, " ", "_"))
  ) |> 
  pivot_wider(
      names_from = Flujo, values_from = Valor
      ) |> 
  mutate(Importaciones = Importaciones/1000000,
         Exportaciones = Exportaciones/1000000) |> 
  group_by(Año, Pais) |>
  summarise(
    Importaciones = sum(Importaciones),
    Exportaciones = sum(Exportaciones),
    .groups = "drop"
  )

Verifiquemos una vez más nombres y clases

str(df1)
tibble [7,755 × 4] (S3: tbl_df/tbl/data.frame)
 $ Año          : int [1:7755] 1993 1993 1993 1993 1993 1993 1993 1993 1993 1993 ...
 $ Pais         : Factor w/ 235 levels "Afganistán","Albania",..: 1 2 3 4 5 6 7 8 9 10 ...
 $ Importaciones: num [1:7755] 0.396 0.082 2852.436 0.012 0.11 ...
 $ Exportaciones: num [1:7755] 0.264 0.067 430.195 0.18 0.007 ...

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

MexXMtotpais <- df1
save(MexXMtotpais, file = here("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 1.

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)
df2 <- as.data.frame(data_list$data)
str(df2)
chaps <- df2 |> filter(`Quarter ID`<19932,`Flow ID` == "1" )|> select(`Chapter 2 Digit ID`,`Chapter 2 Digit`)
chaps
   Chapter 2 Digit ID                   Chapter 2 Digit
1                   1    Los Productos de Origen Animal
2                   2       Productos del Reino Vegetal
3                   3 Animales y Vegetales Bi-Productos
4                   4        Los Productos Alimenticios
5                   5               Productos Minerales
6                   6                Productos Químicos
7                   7               Plásticos y Cauchos
8                   8                Pieles de Animales
9                   9               Productos de Madera
10                 10                Artículos de Papel
11                 11                          Textiles
12                 12              Calzado, y Sombreros
13                 13                  Piedra y Cristal
14                 14                 Metales Preciosos
15                 15                            Rieles
16                 16                          Máquinas
17                 17                        Transporte
18                 18                      Instrumentos
19                 20                           Diverso
save(chaps,file = here("Data", "chaps.RData"))

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”

df2 <- df2 |> select(!ends_with("ID")) |> 
  rename(Trimestre = Quarter,
         Flujo = Flow,
         Capítulo = `Chapter 2 Digit`,
         Valor = `Trade Value`)
str(df2)
'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

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

Separamos Exportaciones e Importaciones y re escalamos

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

Y convertimos Capítulo a factor

df2$Capítulo <- as.factor(df2$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:

df2 <- df2 |> 
  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(df2)
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 <- df2
save(MexXMproducto, file = here("Data", "MexXMproducto.RData"))

Nota: “rieles” parece corresponder, a juzgar por la nomenclatura utilizada en inglés, a “metales”. ## 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=Quarter%2CFlow%2CState&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)
df3 <- as.data.frame(data_list$data)
str(df3)
'data.frame':   5106 obs. of  7 variables:
 $ Quarter ID : int  20061 20061 20061 20061 20061 20061 20061 20061 20061 20061 ...
 $ Quarter    : chr  "2006-Q1" "2006-Q1" "2006-Q1" "2006-Q1" ...
 $ Flow ID    : int  1 1 1 1 1 1 1 1 1 1 ...
 $ Flow       : chr  "Compras internacionales" "Compras internacionales" "Compras internacionales" "Compras internacionales" ...
 $ State ID   : int  1 2 3 4 5 6 7 8 9 10 ...
 $ State      : chr  "Aguascalientes" "Baja California" "Baja California Sur" "Campeche" ...
 $ Trade Value: num  1.05e+09 1.25e+10 9.19e+07 1.24e+08 4.89e+09 ...

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

df3 <- df3 |> 
  select(-`Flow ID`) |> 
  pivot_wider(names_from = Flow, values_from = `Trade Value`)  
  str(df3)
tibble [2,574 × 6] (S3: tbl_df/tbl/data.frame)
 $ Quarter ID             : int [1:2574] 20061 20061 20061 20061 20061 20061 20061 20061 20061 20061 ...
 $ Quarter                : chr [1:2574] "2006-Q1" "2006-Q1" "2006-Q1" "2006-Q1" ...
 $ State ID               : int [1:2574] 1 2 3 4 5 6 7 8 9 10 ...
 $ State                  : chr [1:2574] "Aguascalientes" "Baja California" "Baja California Sur" "Campeche" ...
 $ Compras internacionales: num [1:2574] 1.05e+09 1.25e+10 9.19e+07 1.24e+08 4.89e+09 ...
 $ Ventas internacionales : num [1:2574] 5.83e+08 1.42e+10 6.95e+07 1.35e+08 5.15e+09 ...
df3 <- df3 |> 
  rename(Trim = Quarter,
         IDTrim = `Quarter ID`,
         Estado = State,
         Exportaciones = `Ventas internacionales`,
         Importaciones = `Compras internacionales`) |>
  mutate(Exportaciones = Exportaciones/1000000,
         Importaciones = Importaciones/1000000,
         Estado = as.factor(Estado))

Finalmente, guardamos la base de datos en formato R

XMEstados <- df3
save(XMEstados, file = (here("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_mun&drilldowns=Country%2CYear%2CFlow%2CChapter&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)
dfusap <- as.data.frame(data_list$data)
str(dfusap)
'data.frame':   809 obs. of  8 variables:
 $ Country ID : chr  "usa" "usa" "usa" "usa" ...
 $ Country    : chr  "United States" "United States" "United States" "United States" ...
 $ Year       : int  2006 2006 2006 2006 2006 2006 2006 2006 2006 2006 ...
 $ Flow ID    : int  1 1 1 1 1 1 1 1 1 1 ...
 $ Flow       : chr  "Imports" "Imports" "Imports" "Imports" ...
 $ Chapter ID : int  1 2 3 4 5 6 7 8 9 10 ...
 $ Chapter    : chr  "Animal Products" "Vegetable Products" "Animal and Vegetable Bi-Products" "Foodstuffs" ...
 $ Trade Value: num  9.82e+08 8.66e+08 3.15e+07 1.37e+09 3.58e+09 ...

Ajustes

dfusap <- dfusap |> select(!ends_with("ID")) |> 
  pivot_wider(
    names_from = "Flow",
    values_from = "Trade Value"
    ) |>
  rename(
    Capitulo = Chapter,
    Año = Year,
    Pais = Country,
    Exportaciones = Exports,
    Importaciones = Imports
    ) |> 
  mutate(
    Capitulo = as.factor(Capitulo), 
    Pais = as.factor(Pais)
    ) |> 
  mutate(Capitulo = fct_recode(Capitulo,
                               "Animales" = "Animal Products",
                               "Vegetales" = "Vegetable Products",
                               "Animal_Veg" = "Animal and Vegetable Bi-Products",
                               "Alimentos" = "Foodstuffs",
                               "Minerales" = "Mineral Products",
                               "Quimicos" = "Chemical Products",
                               "Plásticos" = "Plastics and Rubbers",
                               "Pieles" = "Animal Hides",
                               "Madera" = "Wood Products",
                               "Papel" = "Paper Goods",
                               "CalzSomb" = "Footwear and Headwear",
                               "Piedra" = "Stone and Glass",
                               "MPreciosos" = "Precious Metals",
                               "Metales" = "Metals",
                               "ArteyAntig" = "Arts and Antiques",
                               "Instrumentos" = "Instruments",
                               "Otros" = "Miscellaneous",
                               "Maquinas" = "Machines",
                               "Transporte" = "Transportation",
                               "Armas" = "Weapons"),
         Pais = fct_recode(Pais,
                           "USA" = "United States")
    
  )

Almacenamiento

XMUSACap <- dfusap
save(XMUSACap, file =(here("Data", "XMUSACap.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,
         Pais = Country,
         Inversion = Investment) |> 
  mutate(País = as.factor(Pais))
str(df)  
'data.frame':   1191 obs. of  4 variables:
 $ Año      : int  1999 1999 1999 1999 1999 1999 1999 1999 1999 1999 ...
 $ Pais     : chr  "Argentina" "Australia" "Austria" "Belgium" ...
 $ Inversion: num  3.54 1.32 6.2 128.31 17.63 ...
 $ País     : Factor w/ 50 levels "Argentina","Australia",..: 1 2 3 4 6 7 45 8 9 10 ...
# los acentos se han omitido deliberadamente, para facilitar la codificación posterior.  A veces R se confunde si hay nombres de variables de más de una palabra (que obliga a entrecomillarlos) o en presencia de acentos.

Esta base de datos tiene información sobre 50 orígenes de inversión en México. Vamos a seleccionar los 10 más importantes. El primer paso es identificar esos países, tomando en cuenta el volumen de inversión de los últimos cindo años.

top_10_countries <- df |>
  filter(Año >= 2020 & Año <= 2024) |>
  filter(País != "Unknown") |> # categoría residual en la base de datos que no nos interesa
  group_by(País) |>
  summarise(Total_Inversion = sum(Inversion, na.rm = TRUE)) |>
  # sumamos porque queremos los países que más invirtieron en el período completo, no en un año aislado
  slice_max(order_by = Total_Inversion, n = 10) |> # ordenamos de mayor a manor y seleccionamos los 10 más altos
  pull(País) # extraemos la variable que nos interesa

Ahora que tenemos la lista de los diez orígenes más importantes, creamos una base de datos que solo incluye estos orígenes

df2 <- df |> 
  mutate(Pais = if_else(Pais %in% top_10_countries, as.character(Pais), "Otros")) |>
  # crea "Otros" como categoría residual
  group_by(Año, Pais) |> # nos permite sumar por Año en el paso siguiente.  Relevante solo para la categoría "otros"
  summarise(Inversion = sum(Inversion, na.rm = TRUE), .groups = "drop") |> 
  mutate(Pais = as.factor(Pais))

Todavía tenemos que dar un paso más. Los nombres de los países están almacenados en inglés, y en algunos casos están compuestos de dos palabras:

levels(df2$Pais)
 [1] "Argentina"      "Belgium"        "Canada"         "Germany"       
 [5] "Japan"          "Netherlands"    "Otros"          "South Korea"   
 [9] "Spain"          "United Kingdom" "United States" 

Traducimos los nombres a castellano, y evitamos los nombres de dos palabras

df2 <- df2 |> 
  mutate(
    Pais = fct_recode(Pais,
                      "Belgica" = "Belgium",
                      "Alemania" = "Germany",
                      "Japon" = "Japan",
                      "PaisesBajos" = "Netherlands",
                      "CoreaS" = "South Korea",
                      "Espana" = "Spain",
                      "RU" = "United Kingdom",
                      "USA" = "United States")
  )

Almacenamiento

IEDPais <- df2
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)
immex <- tidy_IMMEX |> 
  pivot_wider(
    names_from = Variable,
    values_from = Value) |> 
  clean_names() |> 
  rename(
    Año = year,
    Mes = month,
    Establecimientos = numero_de_establecimientos_activos,
    Trabajadores = total_de_personal_ocupado_por_condicion_de_contratacion_y_calificacion_de_la_mano_de_obra_numero_de_personas,
    Remuneraciones = remuneraciones_pagadas_al_personal_ocupado_miles_de_pesos,
    Salarios = total_de_salarios_y_sueldos_pagados_al_personal_miles_de_pesos,
    Horas = total_de_horas_trabajadas_por_el_personal_ocupado_miles_de_horas,
    VentasMX = total_de_ingresos_provenientes_del_mercado_nacional_miles_de_pesos,
    MaqManuf = maquila_submaquila_y_remanufactura_miles_de_pesos,
    Exportaciones = total_de_ingresos_provenientes_del_mercado_extranjero_miles_de_pesos,
    Rem_Manuf = total_de_remuneraciones_reales_por_persona_ocupada_en_los_establecimientos_manufactureros_pesos
  ) |> 
  mutate(
    # 1. Translate Spanish month names to month numbers
    Mes_Num = case_when(
      Mes == "Enero" ~ 1,
      Mes == "Febrero" ~ 2,
      Mes == "Marzo" ~ 3,
      Mes == "Abril" ~ 4,
      Mes == "Mayo" ~ 5,
      Mes == "Junio" ~ 6,
      Mes == "Julio" ~ 7,
      Mes == "Agosto" ~ 8,
      Mes == "Septiembre" ~ 9,
      Mes == "Octubre" ~ 10,
      Mes == "Noviembre" ~ 11,
      Mes == "Diciembre" ~ 12
    ),
    # 2. Combine year, month, and day (using the 1st day of the month)
    #    and convert to a date object
    Fecha = make_date(year = Año, month = Mes_Num, day = 1)
  ) |> 
  mutate(entidad = factor(entidad)) |> 
  mutate(
    entidad = fct_recode(entidad,
                         "BAJA" = "BAJA CALIFORNIA",
                         "CDMX" = "CIUDAD DE MÉXICO",
                         "S_Catarina" = "Santa Catarina",
                         "TOTAL" = "TOTAL NACIONAL",
                         "COAHUILA" = "COAHUILA DE ZARAGOZA",
                         "POTOSI" = "SAN LUIS POTOSÍ",
                         "VERACRUZ" = "VERACRUZ DE IGNACIO DE LA LLAVE",
                         "N_LEON" = "NUEVO LEÓN",
                         "Ramos" = "Ramos Arizpe",
                         "S_Nicolás" = "San Nicolás de los Garza"
                        )
  )
save(immex, file = here("Data", "immex.RData"))