Equipo 4: Estoicos
Integrantes:
- Alan Plácido Herrera
- Sebastián Alberto Chávez Medina
- Isaac Ismael Coronel Ceballos
- Mia Fernanda Díaz Flores
- Pedro Emilio Juárez Muñoz
Las relaciones comerciales que México mantiene con Estados Unidos y China tienen un impacto directo en el comportamiento de sus exportaciones e importaciones de cobre, posicionando a este metal como un recurso estratégico para la economía nacional.
Analizar la relación entre las exportaciones e importaciones de cobre en México y sus principales socios comerciales, para entender su relevancia en el desarrollo económico y comercial del país.
¿En qué medida la sensibilidad al precio del cobre, estimada a través de elasticidades por país, puede utilizarse como criterio para priorizar destinos estratégicos en la política comercial de exportaciones mexicanas?
if(require(RColorBrewer) == FALSE){
install.packages("RColorBrewer")
library(RColorBrewer) #Colores bonitos
} else {
library(RColorBrewer)
}
## Loading required package: RColorBrewer
if(require(broom) == FALSE){
install.packages("broom")
library(broom) #Modelos → data frame
} else {
library(broom)
}
## Loading required package: broom
if(require(countrycode) == FALSE){
install.packages("countrycode")
library(countrycode) #Códigos de países
} else {
library(countrycode)
}
## Loading required package: countrycode
if(require(dplyr) == FALSE){
install.packages("dplyr")
library(dplyr) #Manipular datos
} else {
library(dplyr)
}
## Loading required package: dplyr
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
if(require(geosphere) == FALSE){
install.packages("geosphere")
library(geosphere) #Distancias geográficas
} else {
library(geosphere)
}
## Loading required package: geosphere
if(require(ggplot2) == FALSE){
install.packages("ggplot2")
library(ggplot2) #Gráficas
} else {
library(ggplot2)
}
## Loading required package: ggplot2
if(require(ggraph) == FALSE){
install.packages("ggraph")
library(ggraph) #Redes/Grafos
} else {
library(ggraph)
}
## Loading required package: ggraph
if(require(ggrepel) == FALSE){
install.packages("ggrepel")
library(ggrepel) #Etiquetas en gráficos
} else {
library(ggrepel)
}
## Loading required package: ggrepel
if(require(hrbrthemes) == FALSE){
install.packages("hrbrthemes")
library(hrbrthemes) #Temas elegantes
} else {
library(hrbrthemes)
}
## Loading required package: hrbrthemes
if(require(htmlwidgets) == FALSE){
install.packages("htmlwidgets")
library(htmlwidgets) #Gráficos interactivos
} else {
library(htmlwidgets)
}
## Loading required package: htmlwidgets
if(require(janitor) == FALSE){
install.packages("janitor")
library(janitor) #Limpiar
} else {
library(janitor)
}
## Loading required package: janitor
##
## Attaching package: 'janitor'
## The following objects are masked from 'package:stats':
##
## chisq.test, fisher.test
if(require(networkD3) == FALSE){
install.packages("networkD3")
library(networkD3) #Sankey y redes HTML
} else {
library(networkD3)
}
## Loading required package: networkD3
##
## Attaching package: 'networkD3'
## The following object is masked from 'package:htmlwidgets':
##
## JS
if(require(plm) == FALSE){
install.packages("plm")
library(plm) #Panel data
} else {
library(plm)
}
## Loading required package: plm
##
## Attaching package: 'plm'
## The following objects are masked from 'package:dplyr':
##
## between, lag, lead
if(require(purrr) == FALSE){
install.packages("purrr")
library(purrr) #Map y loops
} else {
library(purrr)
}
## Loading required package: purrr
if(require(readr) == FALSE){
install.packages("readr")
library(readr) #Leer CSVs
} else {
library(readr)
}
## Loading required package: readr
if(require(scales) == FALSE){
install.packages("scales")
library(scales) #Escalas en gráficos
} else {
library(scales)
}
## Loading required package: scales
##
## Attaching package: 'scales'
## The following object is masked from 'package:readr':
##
## col_factor
## The following object is masked from 'package:purrr':
##
## discard
if(require(sf) == FALSE){
install.packages("sf")
library(sf) #Mapas
} else {
library(sf)
}
## Loading required package: sf
## Linking to GEOS 3.13.0, GDAL 3.8.5, PROJ 9.5.1; sf_use_s2() is TRUE
if(require(st) == FALSE){
install.packages("st")
library(st) #Espacial
} else {
library(st)
}
## Loading required package: st
## Loading required package: sda
## Loading required package: entropy
## Loading required package: corpcor
## Loading required package: fdrtool
if(require(stringi) == FALSE){
install.packages("stringi")
library(stringi) #Texto (potente)
} else {
library(stringi)
}
## Loading required package: stringi
if(require(stringr) == FALSE){
install.packages("stringr")
library(stringr) #Texto (fácil)
} else {
library(stringr)
}
## Loading required package: stringr
if(require(tidygraph) == FALSE){
install.packages("tidygraph")
library(tidygraph) #Grafo en tidy
} else {
library(tidygraph)
}
## Loading required package: tidygraph
##
## Attaching package: 'tidygraph'
## The following object is masked from 'package:stats':
##
## filter
if(require(tidyverse) == FALSE){
install.packages("tidyverse")
library(tidyverse) #Todo el kit
} else {
library(tidyverse)
}
## Loading required package: tidyverse
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ forcats 1.0.0 ✔ tibble 3.2.1
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ plm::between() masks dplyr::between()
## ✖ scales::col_factor() masks readr::col_factor()
## ✖ scales::discard() masks purrr::discard()
## ✖ tidygraph::filter() masks dplyr::filter(), stats::filter()
## ✖ plm::lag() masks dplyr::lag(), stats::lag()
## ✖ plm::lead() masks dplyr::lead()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
if(require(viridis) == FALSE){
install.packages("viridis")
library(viridis) #Colores accesibles
} else {
library(viridis)
}
## Loading required package: viridis
## Loading required package: viridisLite
##
## Attaching package: 'viridis'
##
## The following object is masked from 'package:scales':
##
## viridis_pal
Se muestran los flujos acumulados de comercio internacional de cobre entre los estados mexicanos y sus socios globales durante el periodo 2007–2024.
Fuente: Data México. Producto: Minerales de Cobre y sus Concentrados (Código 2603, Sistema Armonizado 2012, 4 dígitos).
# DATA --------------------------------------------------------------------
data <- read_csv("/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/UN TRADE/map.csv") %>%
clean_names() %>%
filter(hs4_4_digit_id == 52603)
## Rows: 877162 Columns: 9
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (5): HS4 4 Digit, Country ID, Country, State, Flow
## dbl (4): HS4 4 Digit ID, State ID, Flow ID, Trade Value
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# RED Estados de México y Mundo ESPAÑOL ---------------------------------------
# Diccionario: países en español
traducciones_paises <- c(
"Argentina" = "Argentina",
"Australia" = "Australia",
"Austria" = "Austria",
"Belgium" = "Bélgica",
"Bulgaria" = "Bulgaria",
"Bolivia" = "Bolivia",
"Brazil" = "Brasil",
"Canada" = "Canadá",
"Switzerland" = "Suiza",
"Chile" = "Chile",
"China" = "China",
"Republic of the Congo" = "República del Congo",
"Colombia" = "Colombia",
"Germany" = "Alemania",
"Ecuador" = "Ecuador",
"Spain" = "España",
"France" = "Francia",
"United Kingdom" = "Reino Unido",
"Hong Kong" = "Hong Kong",
"Indonesia" = "Indonesia",
"India" = "India",
"Italy" = "Italia",
"Japan" = "Japón",
"Kazakhstan" = "Kazajistán",
"Cambodia" = "Camboya",
"South Korea" = "Corea del Sur",
"Luxembourg" = "Luxemburgo",
"Morocco" = "Marruecos",
"Macedonia" = "Macedonia",
"Malaysia" = "Malasia",
"Netherlands" = "Países Bajos",
"Panama" = "Panamá",
"Peru" = "Perú",
"Philippines" = "Filipinas",
"Poland" = "Polonia",
"Russia" = "Rusia",
"Saudi Arabia" = "Arabia Saudita",
"Singapore" = "Singapur",
"Sweden" = "Suecia",
"Eswatini" = "Esuatini",
"Thailand" = "Tailandia",
"Tunisia" = "Túnez",
"Taiwan (Republic of China)" = "Taiwán",
"Tanzania" = "Tanzania",
"Uruguay" = "Uruguay",
"United States" = "Estados Unidos",
"Vietnam" = "Vietnam",
"South Africa" = "Sudáfrica",
"Zambia" = "Zambia"
)
# Diccionario: tipo de flujo
traducciones_flujo <- c(
"Exports" = "Exportaciones",
"Imports" = "Importaciones"
)
# Crear conexiones: origen, destino, tipo y valor
edges <- data %>%
group_by(state, country, flow) %>%
summarise(peso = sum(trade_value), .groups = "drop") %>%
rename(from = state, to = country) %>%
mutate(
to = recode(to, !!!traducciones_paises), # país en español
flujo = recode(flow, !!!traducciones_flujo) # flujo en español
) %>%
select(from, to, peso, flujo)
# Crear nodos: estados y países
nodos <- tibble(nombre = unique(c(edges$from, edges$to))) %>%
mutate(
tipo = if_else(nombre %in% unique(data$state), "Estado", "País"), # origen o destino
color = case_when(
tipo == "Estado" ~ "#2C3E50", # azul oscuro
tipo == "País" ~ "#E67E22" # naranja
)
)
# Crear grafo y calcular grado de conexión
grafo <- tbl_graph(nodes = nodos, edges = edges, directed = TRUE) %>%
mutate(grado = centrality_degree(mode = "all"))
# Visualizar red circular
ggraph(grafo, layout = "circle") +
geom_edge_arc(aes(width = peso, color = flujo),
arrow = arrow(length = unit(3, "mm")),
end_cap = circle(3, "mm"),
alpha = 0.6) +
geom_node_point(aes(size = grado, color = tipo), show.legend = FALSE) +
geom_node_text(aes(label = nombre), repel = TRUE, size = 3) +
scale_edge_width(range = c(0.2, 1.5), name = "Valor del comercio") +
scale_edge_color_manual(
values = c("Exportaciones" = "#E74C3C", "Importaciones" = "#3498DB"),
name = "Flujo"
) +
scale_size(range = c(2, 7), name = "Grado del nodo") +
scale_color_manual(
values = c("Estado" = "#2C3E50", "País" = "#E67E22"),
name = "Tipo de nodo"
) +
theme_void() +
labs(
title = "Red circular del comercio de cobre entre Estados y Países",
subtitle = "Nodos por grado, flechas por flujo, colores por tipo"
)
## Warning: ggrepel: 1 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps
El mapa muestra cómo se distribuyeron las exportaciones mexicanas de cobre entre los estados durante 2024. Los datos reflejan una concentración territorial muy marcada:
Esta configuración muestra una fuerte centralización del comercio exterior de cobre, en contraste con la red acumulada del periodo 2007–2024.
El hecho de que solo unos pocos estados participen activamente puede tener efectos importantes sobre cómo el país organiza su industria y su estrategia comercial.
Fuente: Data México. Producto: Minerales de Cobre y sus Concentrados (Código 2603, Sistema Armonizado 2012, 4 dígitos).
mexico <- st_read("/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/entidades") %>%
st_simplify(dTolerance = 5000) %>%
st_make_valid()
## Reading layer `00ent' from data source
## `/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/entidades'
## using driver `ESRI Shapefile'
## Simple feature collection with 32 features and 3 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: 911292 ymin: 319149.1 xmax: 4082997 ymax: 2349615
## Projected CRS: MEXICO_ITRF_2008_LCC
glimpse(mexico)
## Rows: 32
## Columns: 4
## $ CVEGEO <chr> "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "…
## $ CVE_ENT <chr> "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "…
## $ NOMGEO <chr> "Aguascalientes", "Baja California", "Baja California Sur", "…
## $ geometry <GEOMETRY [m]> POLYGON ((2484292 1141119, ..., MULTIPOLYGON (((1203…
Mex <- read_csv("/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/UN TRADE/mex.csv") %>%
clean_names()
## Rows: 3 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): State
## dbl (3): State ID, Trade Value, Share
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
mexico_export <- mexico %>%
left_join(Mex, by = c("NOMGEO" = "state"))
ggplot(mexico_export) +
geom_sf(aes(fill = !is.na(trade_value)), color = "white", size = 0.3) +
geom_sf_text(
data = subset(mexico_export, !is.na(trade_value)),
aes(label = paste0(NOMGEO, "\nUSD ", format(round(trade_value / 1e6, 1), nsmall = 1), " M")),
size = 3.2,
color = "black",
lineheight = 1
) +
scale_fill_manual(
values = c("TRUE" = "#238b45", "FALSE" = "#e0e0e0"),
labels = c("TRUE" = "Exportó", "FALSE" = "No exportó")
) +
labs(
title = "Exportaciones estatales de México en 2024",
subtitle = "Estados que reportaron exportaciones de cobre (valores en millones USD)",
fill = "",
caption = "Fuente: Data México. Producto: Minerales de Cobre y sus Concentrados, procesamiento propio"
) +
theme_minimal(base_family = "Helvetica") +
theme(
plot.title = element_text(size = 18, face = "bold", hjust = 0.5),
plot.subtitle = element_text(size = 13, margin = margin(b = 10), hjust = 0.5),
legend.position = "bottom",
legend.text = element_text(size = 11),
plot.caption = element_text(size = 9, hjust = 1),
panel.grid = element_blank()
)
total_export <- sum(mexico_export$trade_value, na.rm = TRUE)
export_porcentajes <- mexico_export %>%
filter(!is.na(trade_value)) %>%
mutate(
export_millones = round(trade_value / 1e6, 1),
porcentaje = round(100 * trade_value / total_export, 2)
) %>%
select(NOMGEO, export_millones, porcentaje) %>%
arrange(desc(porcentaje))
print(export_porcentajes)
## Simple feature collection with 3 features and 3 fields
## Geometry type: GEOMETRY
## Dimension: XY
## Bounding box: xmin: 1263787 ymin: 1020248 xmax: 2876730 ymax: 2324237
## Projected CRS: MEXICO_ITRF_2008_LCC
## NOMGEO export_millones porcentaje
## 1 Sonora 3146.9 96.07
## 2 Coahuila de Zaragoza 121.0 3.70
## 3 San Luis Potosí 7.8 0.24
## geometry
## 1 MULTIPOLYGON (((1508694 191...
## 2 POLYGON ((2469954 1978523, ...
## 3 POLYGON ((2640890 1374316, ...
En 2024, China fue el principal destino de las exportaciones
mexicanas de cobre, mientras que una parte
significativa de las importaciones provino de Estados
Unidos.
Este patrón refleja una dinámica triangular: México
compra cobre a EE.UU. y lo exporta principalmente a China.
_Fuente: *UN Comtrade (United Nations Commodity Trade Statistics Database). Producto: Minerales de Cobre y sus Concentrados (Código 2603, Sistema Armonizado 2012, 4 dígitos)._
# RED DE COMERCIO DE MÉXICO ESPAÑOL -----------------------------------------------------------------------------
library(tidyverse)
library(janitor)
library(tidygraph)
library(ggraph)
# 1) Vectores de traducción
traducciones_paises <- c(
"Argentina" = "Argentina",
"Australia" = "Australia",
"Austria" = "Austria",
"Belgium" = "Bélgica",
"Bulgaria" = "Bulgaria",
"Bolivia" = "Bolivia",
"Brazil" = "Brasil",
"Canada" = "Canadá",
"Switzerland" = "Suiza",
"Chile" = "Chile",
"China" = "China",
"Republic of the Congo" = "República del Congo",
"Colombia" = "Colombia",
"Germany" = "Alemania",
"Ecuador" = "Ecuador",
"Spain" = "España",
"France" = "Francia",
"United Kingdom" = "Reino Unido",
"Hong Kong" = "Hong Kong",
"Indonesia" = "Indonesia",
"India" = "India",
"Italy" = "Italia",
"Japan" = "Japón",
"Kazakhstan" = "Kazajistán",
"Cambodia" = "Camboya",
"South Korea" = "Corea del Sur",
"Luxembourg" = "Luxemburgo",
"Morocco" = "Marruecos",
"Macedonia" = "Macedonia",
"Malaysia" = "Malasia",
"Netherlands" = "Países Bajos",
"Panama" = "Panamá",
"Peru" = "Perú",
"Philippines" = "Filipinas",
"Poland" = "Polonia",
"Russia" = "Rusia",
"Saudi Arabia" = "Arabia Saudita",
"Singapore" = "Singapur",
"Sweden" = "Suecia",
"Eswatini" = "Esuatini",
"Thailand" = "Tailandia",
"Tunisia" = "Túnez",
"Taiwan (Republic of China)" = "Taiwán",
"Tanzania" = "Tanzania",
"Uruguay" = "Uruguay",
"United States" = "Estados Unidos",
"Vietnam" = "Vietnam",
"South Africa" = "Sudáfrica",
"Zambia" = "Zambia",
# Aquí la traducción de Turquía:
"T\xfcrkiye" = "Turquía",
"Turkiye" = "Turquía"
)
traducciones_flujo <- c(
"Export" = "Exportaciones",
"Import" = "Importaciones"
)
# 2) Cargar y filtrar datos para 2024
data <- read_csv("/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/UN TRADE/FINAL.csv", show_col_types = FALSE) %>%
clean_names()
## Warning: One or more parsing issues, call `problems()` on your data frame for details,
## e.g.:
## dat <- vroom(...)
## problems(dat)
edges <- data %>%
filter(
ref_year == 2024,
(reporter_desc == "Mexico" | partner_desc == "Mexico"),
reporter_desc != "World",
partner_desc != "World",
primary_value > 0
) %>%
group_by(reporter_desc, partner_desc, flow_desc) %>%
summarise(peso = sum(primary_value, na.rm = TRUE), .groups = "drop") %>%
rename(from = reporter_desc,
to = partner_desc,
flujo_orig = flow_desc) %>%
# 3) Traducir nombres y flujo
mutate(
from = recode(from, "Mexico" = "México", !!!traducciones_paises),
to = recode(to, "Mexico" = "México", !!!traducciones_paises),
flujo = recode(flujo_orig, !!!traducciones_flujo)
) %>%
select(from, to, peso, flujo)
# 4) Crear nodos y asignar color: Turquía en negro, resto en gris oscuro
nodos <- tibble(nombre = unique(c(edges$from, edges$to))) %>%
mutate(
color = if_else(nombre == "Turquía",
"#000000", # Turquía en negro
"#2C3E50") # Resto en gris oscuro
)
# 5) Construir grafo y calcular grado
grafo <- tbl_graph(nodes = nodos, edges = edges, directed = TRUE) %>%
mutate(grado = centrality_degree(mode = "all"))
# 6) Visualizar la red circular
ggraph(grafo, layout = "circle") +
geom_edge_arc(aes(width = peso, color = flujo),
arrow = arrow(length = unit(3, "mm")),
end_cap = circle(3, "mm"),
alpha = 0.6) +
geom_node_point(aes(size = grado, colour = color), show.legend = FALSE) +
geom_node_text(aes(label = nombre), repel = TRUE, size = 2.8) +
scale_edge_width(range = c(0.2, 1.5), name = "Valor del comercio") +
scale_edge_color_manual(
values = c("Exportaciones" = "#00796B", "Importaciones" = "#E64A19"),
name = "Flujo"
) +
scale_size(range = c(2, 7), name = "Grado del nodo") +
scale_colour_identity() +
theme_void() +
labs(
title = "Red de comercio de cobre de México (2024)",
subtitle = "Exportaciones e importaciones entre México y sus socios"
)
# Exportaciones Mundo -----------------------------------------------------
data <- read_csv("/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/UN TRADE/FINAL.csv",
locale = locale(encoding = "UTF-8")) %>%
clean_names()
## Warning: One or more parsing issues, call `problems()` on your data frame for details,
## e.g.:
## dat <- vroom(...)
## problems(dat)
## Rows: 12217 Columns: 47
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (19): typeCode, freqCode, reporterISO, reporterDesc, flowCode, flowDesc,...
## dbl (21): refPeriodId, refYear, refMonth, period, reporterCode, partnerCode,...
## lgl (7): isOriginalClassification, isLeaf, isQtyEstimated, isAltQtyEstimate...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
exportaciones_mex <- data %>%
filter(ref_year == 2024,
flow_desc == "Export",
reporter_desc == "Mexico",
cmd_code == 2603,
primary_value > 0,
net_wgt > 0,
!is.na(partner_desc),
partner_desc != "World") %>%
select(destino = partner_desc, valor_total = primary_value)
importaciones_desde_mex <- data %>%
filter(ref_year == 2024,
flow_desc == "Import",
partner_desc == "Mexico",
cmd_code == 2603,
primary_value > 0,
net_wgt > 0,
!is.na(reporter_desc),
reporter_desc != "World") %>%
select(destino = reporter_desc, valor_total = primary_value)
paises_ya_reportados <- unique(exportaciones_mex$destino)
importaciones_filtradas <- importaciones_desde_mex %>%
filter(!(destino %in% paises_ya_reportados))
exportaciones_corregidas <- bind_rows(exportaciones_mex, importaciones_filtradas) %>%
group_by(destino) %>%
summarise(valor_total = sum(valor_total, na.rm = TRUE), .groups = "drop")
total_exportado <- sum(exportaciones_corregidas$valor_total, na.rm = TRUE)
exportaciones_corregidas <- exportaciones_corregidas %>%
mutate(
destino = case_when(
destino == "Germany" ~ "Alemania",
destino == "Spain" ~ "España",
destino == "Canada" ~ "Canadá",
destino == "Philippines" ~ "Filipinas",
destino == "Rep. of Korea" ~ "Corea del Sur",
destino == "Japan" ~ "Japón",
destino == "Malaysia" ~ "Malasia",
destino == "Netherlands" ~ "Países Bajos",
destino == "T\xfcrkiye" ~ "Turquía",
TRUE ~ destino
),
porcentaje = valor_total / total_exportado * 100,
destino_etiqueta = paste0(
destino, " (",
ifelse(porcentaje < 0.1, "<0.1", sprintf("%.1f", porcentaje)),
"%)"
),
destino_match = recode(destino,
"Alemania" = "Germany",
"España" = "Spain",
"Canadá" = "Canada",
"Filipinas" = "Philippines",
"Corea del Sur" = "South Korea",
"Japón" = "Japan",
"Malasia" = "Malaysia",
"Países Bajos" = "Netherlands",
"Turquía" = "Turkey",
"China" = "China",
"Chile" = "Chile"
)
)
world <- st_read("/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/world")
## Reading layer `world-administrative-boundaries' from data source
## `/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/world'
## using driver `ESRI Shapefile'
## Simple feature collection with 256 features and 8 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: -180 ymin: -58.49861 xmax: 180 ymax: 83.6236
## Geodetic CRS: WGS 84
world_export <- world %>%
left_join(exportaciones_corregidas, by = c("name" = "destino_match"))
ggplot(world_export) +
geom_sf(aes(fill = !is.na(valor_total)), color = "white", size = 0.1) +
geom_text_repel(
data = subset(world_export, !is.na(valor_total)),
aes(geometry = geometry, label = destino_etiqueta),
stat = "sf_coordinates",
size = 4.5,
color = "black",
min.segment.length = 0,
segment.size = 0.3,
max.overlaps = 100
) +
scale_fill_manual(
name = "Exportaciones reportadas por México",
values = c("TRUE" = "#007849", "FALSE" = "#f0f0f0"),
labels = c("TRUE" = "Exportó (venta)", "FALSE" = "No exportó")
) +
labs(
title = "Exportaciones de Cobre desde México (2024)",
subtitle = "Países de destino y porcentaje del total exportado",
caption = "Fuente: UN Comtrade"
) +
coord_sf(crs = "+proj=robin") +
theme_void(base_family = "Helvetica") +
theme(
plot.title = element_text(size = 18, face = "bold", hjust = 0.5),
plot.subtitle = element_text(size = 14, hjust = 0.5),
legend.position = "bottom",
legend.title = element_text(size = 12, face = "bold"),
legend.text = element_text(size = 11),
plot.caption = element_text(size = 9, hjust = 1)
)
Durante el periodo 2018–2024, México mantuvo consistentemente una balanza comercial superavitaria en el comercio exterior de cobre. Es decir, las exportaciones superaron a las importaciones en todos los años analizados.
2019 marcó un punto alto inicial, con un fuerte incremento en exportaciones.
En 2020, la pandemia por COVID-19 provocó una contracción significativa en el comercio, reflejada en una caída tanto de exportaciones como del superávit.
A partir de 2021, la balanza se recupera rápidamente. Se destaca 2023, con el mayor superávit del periodo.
En 2024, las exportaciones alcanzan su máximo histórico, superando los 4,300 millones de USD, lo que consolida la posición de México como exportador neto de cobre.
## # A tibble: 7 × 4
## Año Exportaciones Importaciones Balanza
## <dbl> <dbl> <dbl> <dbl>
## 1 2018 2622552841. 1184908868. 1437643973.
## 2 2019 4781940680. 1666376908 3115563772.
## 3 2020 2973031273. 1149019624. 1824011649.
## 4 2021 3577591509. 501244857. 3076346653.
## 5 2022 3460567690. 765161266. 2695406424.
## 6 2023 4252235974. 672547172. 3579688803.
## 7 2024 4315432489. 1138457428. 3176975061.
Se muestra la red comercial de cobre en 2024, destacando los principales países exportadores y los destinos hacia donde se dirige la mayor parte de su producción.
China y Japón se consolidan como los mayores compradores globales de cobre, recibiendo altos volúmenes desde múltiples orígenes. Las conexiones hacia estos países presentan los vínculos más gruesos, indicando su peso dominante en el comercio global.
Chile es el principal nodo exportador, con una fuerte concentración de flujos hacia China. Su vínculo comercial con China es el más robusto de toda la red, lo que confirma su rol estratégico en el suministro de cobre a Asia.
México aparece como un exportador relevante pero no central, con conexiones visibles hacia países como China, Alemania y España, aunque su volumen es considerablemente menor comparado con Chile, Perú o Indonesia.
Otros exportadores importantes como Perú, Indonesia, Canadá, y Australia también muestran múltiples vínculos comerciales hacia Asia y Europa, consolidando un mapa donde Asia Oriental lidera la demanda y América Latina lidera la oferta.
México, aunque activo, se encuentra en una posición secundaria en el volumen global exportado, lo que sugiere oportunidades para expandir presencia internacional si se fortalece competitividad frente a líderes regionales.
La alta concentración de compradores en Asia, especialmente China, implica riesgos de dependencia, pero también ventanas estratégicas para países que busquen diversificar o escalar su participación.
library(tidyverse)
library(janitor)
data_exports <- read_csv("/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/UN TRADE/FINAL.csv",
locale = locale(encoding = "UTF-8")) %>%
clean_names()
## Warning: One or more parsing issues, call `problems()` on your data frame for details,
## e.g.:
## dat <- vroom(...)
## problems(dat)
## Rows: 12217 Columns: 47
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (19): typeCode, freqCode, reporterISO, reporterDesc, flowCode, flowDesc,...
## dbl (21): refPeriodId, refYear, refMonth, period, reporterCode, partnerCode,...
## lgl (7): isOriginalClassification, isLeaf, isQtyEstimated, isAltQtyEstimate...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
exportaciones_mundiales <- data_exports %>%
filter(ref_year == 2024,
flow_desc == "Export",
cmd_code == 2603,
primary_value > 0,
net_wgt > 0,
!is.na(partner_desc),
partner_desc != "World") %>%
select(pais = reporter_desc, destino = partner_desc, valor_total = primary_value)
importaciones_reportadas <- data_exports %>%
filter(ref_year == 2024,
flow_desc == "Import",
cmd_code == 2603,
primary_value > 0,
net_wgt > 0,
partner_desc != "World",
!is.na(reporter_desc),
!is.na(partner_desc)) %>%
select(pais = partner_desc, destino = reporter_desc, valor_total = primary_value)
ya_reportados <- exportaciones_mundiales %>%
mutate(pais_dest = paste(pais, destino)) %>%
pull(pais_dest)
importaciones_sin_repetir <- importaciones_reportadas %>%
mutate(pais_dest = paste(pais, destino)) %>%
filter(!(pais_dest %in% ya_reportados)) %>%
select(-pais_dest)
exportaciones_corregidas <- bind_rows(exportaciones_mundiales, importaciones_sin_repetir) %>%
group_by(pais) %>%
summarise(valor_exportado_total = sum(valor_total, na.rm = TRUE), .groups = "drop") %>%
arrange(desc(valor_exportado_total))
top_10_exportadores <- exportaciones_corregidas %>%
slice_head(n = 10)
total_exportado_mundial <- sum(exportaciones_corregidas$valor_exportado_total, na.rm = TRUE)
print(top_10_exportadores)
## # A tibble: 10 × 2
## pais valor_exportado_total
## <chr> <dbl>
## 1 Chile 31293683035.
## 2 Indonesia 8091137319.
## 3 Canada 7544682678.
## 4 Peru 6283865609.
## 5 Australia 4722630240.
## 6 Mexico 4315432489.
## 7 Brazil 4160172027.
## 8 USA 3532340664.
## 9 Ecuador 2213611252.
## 10 Spain 2107710956.
cat("\n Exportaciones mundiales totales de cobre en 2024 (USD):",
scales::comma(total_exportado_mundial), "\n")
##
## Exportaciones mundiales totales de cobre en 2024 (USD): 85,090,633,747
if(require(tidyverse) == FALSE){
install.packages("tidyverse")
library(tidyverse)
} else {
library(tidyverse)
}
if(require(janitor) == FALSE){
install.packages("janitor")
library(janitor)
} else {
library(janitor)
}
data_imports <- read_csv("/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/UN TRADE/FINAL.csv",
locale = locale(encoding = "UTF-8")) %>%
clean_names()
## Warning: One or more parsing issues, call `problems()` on your data frame for details,
## e.g.:
## dat <- vroom(...)
## problems(dat)
## Rows: 12217 Columns: 47
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (19): typeCode, freqCode, reporterISO, reporterDesc, flowCode, flowDesc,...
## dbl (21): refPeriodId, refYear, refMonth, period, reporterCode, partnerCode,...
## lgl (7): isOriginalClassification, isLeaf, isQtyEstimated, isAltQtyEstimate...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
importaciones_mundiales <- data_imports %>%
filter(ref_year == 2024,
flow_desc == "Import",
cmd_code == 2603,
primary_value > 0,
net_wgt > 0,
!is.na(partner_desc),
partner_desc != "World",
partner_desc != "Areas, nes") %>%
select(pais = reporter_desc, origen = partner_desc, valor_total = primary_value)
exportaciones_reportadas <- data_imports %>%
filter(ref_year == 2024,
flow_desc == "Export",
cmd_code == 2603,
primary_value > 0,
net_wgt > 0,
!is.na(reporter_desc),
!is.na(partner_desc),
partner_desc != "World",
partner_desc != "Areas, nes") %>%
select(pais = partner_desc, origen = reporter_desc, valor_total = primary_value)
ya_reportados <- importaciones_mundiales %>%
mutate(pais_origen = paste(pais, origen)) %>%
pull(pais_origen)
exportaciones_sin_repetir <- exportaciones_reportadas %>%
mutate(pais_origen = paste(pais, origen)) %>%
filter(!(pais_origen %in% ya_reportados)) %>%
select(-pais_origen)
importaciones_corregidas <- bind_rows(importaciones_mundiales, exportaciones_sin_repetir) %>%
group_by(pais) %>%
summarise(valor_importado_total = sum(valor_total, na.rm = TRUE), .groups = "drop") %>%
arrange(desc(valor_importado_total))
top_10_importadores <- importaciones_corregidas %>%
slice_head(n = 10)
total_importado_mundial <- sum(importaciones_corregidas$valor_importado_total, na.rm = TRUE)
print(top_10_importadores)
## # A tibble: 10 × 2
## pais valor_importado_total
## <chr> <dbl>
## 1 China 37125499528.
## 2 Japan 13599261599.
## 3 India 7459814515.
## 4 Spain 5163225179.
## 5 Rep. of Korea 5150202935.
## 6 Germany 4975668587.
## 7 Bulgaria 2604290058.
## 8 Philippines 2318092931
## 9 Finland 2159023513.
## 10 Canada 1569891301.
cat("\nImportaciones mundiales totales de cobre en 2024 (USD):",
scales::comma(total_importado_mundial), "\n")
##
## Importaciones mundiales totales de cobre en 2024 (USD): 87,887,410,908
traducciones_paises <- c(
"Ecuador" = "Ecuador",
"Chile" = "Chile",
"Canada" = "Canadá",
"Brazil" = "Brasil",
"Australia" = "Australia",
"Bulgaria" = "Bulgaria",
"Rep. of Korea" = "Corea del Sur",
"Philippines" = "Filipinas",
"Japan" = "Japón",
"India" = "India",
"Germany" = "Alemania",
"Finland" = "Finlandia",
"USA" = "Estados Unidos",
"United States" = "Estados Unidos",
"Spain" = "España",
"Peru" = "Perú",
"Indonesia" = "Indonesia",
"Mexico" = "México",
"China" = "China"
)
exportaciones_top <- bind_rows(exportaciones_mundiales, importaciones_sin_repetir) %>%
filter(
pais %in% top_10_exportadores$pais,
destino %in% top_10_importadores$pais
) %>%
group_by(from = pais, to = destino) %>%
summarise(peso = sum(valor_total, na.rm = TRUE), .groups = "drop") %>%
mutate(
from = recode(from, !!!traducciones_paises),
to = recode(to, !!!traducciones_paises)
)
exportadores <- unique(exportaciones_top$from)
paleta_exp <- brewer.pal(n = max(length(exportadores), 3), name = "Set3")[seq_along(exportadores)]
colores_exportadores <- setNames(paleta_exp, exportadores)
nombres_nodos <- unique(c(exportaciones_top$from, exportaciones_top$to))
nodos <- tibble(nombre = nombres_nodos) %>%
mutate(
tipo = case_when(
nombre %in% exportadores ~ "Exportador",
nombre %in% recode(top_10_importadores$pais, !!!traducciones_paises) ~ "Importador",
TRUE ~ "Otro"
),
color = if_else(tipo == "Exportador",
colores_exportadores[nombre],
"#CCCCCC")
)
exportaciones_top <- exportaciones_top %>%
mutate(color = colores_exportadores[from])
grafo <- tbl_graph(nodes = nodos, edges = exportaciones_top, directed = TRUE) %>%
mutate(grado = centrality_degree(mode = "all"))
ggraph(grafo, layout = "circle") +
geom_edge_arc(aes(width = peso, colour = color),
arrow = arrow(length = unit(3, "mm")),
end_cap = circle(3, "mm"),
alpha = 0.7) +
geom_node_point(aes(size = grado, colour = color), show.legend = FALSE) +
geom_node_text(aes(label = nombre), repel = TRUE, size = 3) +
scale_edge_width(range = c(0.2, 2.8), name = "Peso total") +
scale_edge_colour_identity(
name = "País exportador",
breaks = colores_exportadores,
labels = names(colores_exportadores)
) +
scale_size(range = c(2, 6), name = "Grado del nodo") +
theme_void() +
labs(
title = "Red de exportaciones de cobre (2024)"
)
Se muestra un comparativo de los 10 principales países exportadores e importadores de cobre en 2024, medido en valor monetario (USD).
library(dplyr)
library(ggplot2)
library(scales)
traducciones_paises <- c(
"Chile" = "Chile",
"Indonesia" = "Indonesia",
"Peru" = "Perú",
"Australia" = "Australia",
"Canada" = "Canadá",
"Mexico" = "México",
"Brazil" = "Brasil",
"Spain" = "España",
"USA" = "Estados Unidos",
"China" = "China",
"Japan" = "Japón",
"India" = "India",
"Rep. of Korea" = "Corea del Sur",
"Germany" = "Alemania",
"Bulgaria" = "Bulgaria",
"Philippines" = "Filipinas",
"Finland" = "Finlandia"
)
df_combinado <- bind_rows(
top_10_exportadores %>%
rename(valor = valor_exportado_total) %>%
mutate(tipo = "Exportador"),
top_10_importadores %>%
rename(valor = valor_importado_total) %>%
mutate(tipo = "Importador")
) %>%
mutate(
pais = recode(pais, !!!traducciones_paises)
)
ggplot(df_combinado, aes(
x = reorder(pais, valor),
y = valor,
fill = tipo
)) +
geom_col() +
coord_flip() +
scale_y_continuous(labels = comma) +
facet_wrap(~ tipo, scales = "free") +
scale_fill_manual(
values = c("Exportador" = "#9F2241", "Importador" = "#235B4E")
) +
labs(
title = "Comparativo: Top 10 Exportadores vs Importadores de Cobre (2024)",
x = "País",
y = "Valor (USD)"
) +
theme_minimal() +
theme(legend.position = "none")
País | Exportaciones 2023 (USD) | Exportaciones 2024 (USD) | Cambio absoluto (USD) | Variación (%) |
---|---|---|---|---|
Alemania | 82,701,205 | 187,510,909 | 104,809,704 | +127% |
Corea del Sur | 25,483,007 | 65,486,600 | 39,993,593 | +157% |
China | 3,529,760,559 | 3,718,890,000 | 189,129,441 | +5.4% |
País | Exportaciones 2023 (USD) | Exportaciones 2024 (USD) | Variación (%) |
---|---|---|---|
Japón | 158,682,341 | 20,648,420 | −87% |
Canadá | 140,310,004 | 98,845,570 | −30% |
España | 132,938,069 | 115,918,100 | −12.8% |
Filipinas | 120,989,642 | 104,777,700 | −13.4% |
Malasia | 25,976,163 | 3,349,645 | −87% |
País | Exportaciones 2024 (USD) |
---|---|
Chile | 3,825 |
Países Bajos | 1,724 |
Nota: Aunque aparecen nuevos países en 2024, sus volúmenes son marginales (<0.01%).
data <- read_csv("/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/UN TRADE/FINAL.csv",
locale = locale(encoding = "UTF-8")) %>%
clean_names()
## Warning: One or more parsing issues, call `problems()` on your data frame for details,
## e.g.:
## dat <- vroom(...)
## problems(dat)
## Rows: 12217 Columns: 47
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (19): typeCode, freqCode, reporterISO, reporterDesc, flowCode, flowDesc,...
## dbl (21): refPeriodId, refYear, refMonth, period, reporterCode, partnerCode,...
## lgl (7): isOriginalClassification, isLeaf, isQtyEstimated, isAltQtyEstimate...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
exportaciones_mex <- data %>%
filter(ref_year == 2024,
flow_desc == "Export",
reporter_desc == "Mexico",
cmd_code == 2603,
primary_value > 0,
net_wgt > 0,
!is.na(partner_desc),
partner_desc != "World") %>%
select(destino = partner_desc, valor_total = primary_value)
importaciones_desde_mex <- data %>%
filter(ref_year == 2024,
flow_desc == "Import",
partner_desc == "Mexico",
cmd_code == 2603,
primary_value > 0,
net_wgt > 0,
!is.na(reporter_desc),
reporter_desc != "World") %>%
select(destino = reporter_desc, valor_total = primary_value)
paises_ya_reportados <- unique(exportaciones_mex$destino)
importaciones_filtradas <- importaciones_desde_mex %>%
filter(!(destino %in% paises_ya_reportados))
exportaciones_corregidas <- bind_rows(exportaciones_mex, importaciones_filtradas) %>%
group_by(destino) %>%
summarise(valor_total = sum(valor_total, na.rm = TRUE), .groups = "drop")
exportaciones_corregidas <- exportaciones_corregidas %>%
mutate(destino = case_when(
destino == "China" ~ "China",
destino == "Germany" ~ "Alemania",
destino == "Spain" ~ "España",
destino == "Canada" ~ "Canadá",
destino == "Philippines" ~ "Filipinas",
destino == "Rep. of Korea" ~ "Corea del Sur",
destino == "Japan" ~ "Japón",
destino == "Malaysia" ~ "Malasia",
destino == "Netherlands" ~ "Países Bajos",
destino == "T\xfcrkiye" ~ "Turquía",
destino == "Chile" ~ "Chile",
TRUE ~ destino
))
total_exportado <- sum(exportaciones_corregidas$valor_total, na.rm = TRUE)
sankey_data <- exportaciones_corregidas %>%
mutate(
origen = "México",
porcentaje = valor_total / total_exportado * 100,
destino_etiqueta = paste0(
destino, " (",
ifelse(porcentaje < 0.1, "<0.1", sprintf("%.1f", porcentaje)),
"%)"
)
)
limpiar_utf8 <- function(x) {
x %>%
iconv(from = "", to = "UTF-8", sub = "") %>%
str_replace_all("[^[:print:]]", "") %>%
str_squish()
}
sankey_data <- sankey_data %>%
mutate(
origen = limpiar_utf8(origen),
destino_etiqueta = limpiar_utf8(destino_etiqueta),
valor_total = as.numeric(valor_total)
)
nombres_nodos <- unique(c(sankey_data$origen, sankey_data$destino_etiqueta))
nodes <- data.frame(name = nombres_nodos) %>%
mutate(name = limpiar_utf8(name))
sankey_data <- sankey_data %>%
mutate(
IDsource = match(origen, nodes$name) - 1,
IDtarget = match(destino_etiqueta, nodes$name) - 1
)
missing_ids <- sankey_data %>%
filter(is.na(IDsource) | is.na(IDtarget))
print("⚠️ Flujos con IDs faltantes:")
## [1] "⚠️ Flujos con IDs faltantes:"
print(missing_ids)
## # A tibble: 0 × 7
## # ℹ 7 variables: destino <chr>, valor_total <dbl>, origen <chr>,
## # porcentaje <dbl>, destino_etiqueta <chr>, IDsource <dbl>, IDtarget <dbl>
ColourScal <- 'd3.scaleOrdinal().range([
"#9F2241",
"#BC955C",
"#6F7271",
"#235B4E",
"#DDC9A3",
"#414141",
"#7A6F5F",
"#98989A",
"#003E51"
])'
sankeyNetwork(
Links = sankey_data,
Nodes = nodes,
Source = "IDsource",
Target = "IDtarget",
Value = "valor_total",
NodeID = "name",
sinksRight = TRUE,
colourScale = ColourScal,
nodeWidth = 30,
nodePadding = 16,
fontSize = 13,
iterations = 0
)
## Links is a tbl_df. Converting to a plain data frame.
top10_compradores <- exportaciones_corregidas %>%
arrange(desc(valor_total)) %>%
slice(1:10)
top10_compradores
## # A tibble: 10 × 2
## destino valor_total
## <chr> <dbl>
## 1 China 3718889902
## 2 Alemania 187510935.
## 3 España 115918076.
## 4 Filipinas 104777691
## 5 Canadá 98845571.
## 6 Corea del Sur 65486602
## 7 Japón 20648419.
## 8 Malasia 3349645.
## 9 Chile 3825.
## 10 Países Bajos 1724.
limpiar_utf8 <- function(x) {
x %>%
iconv(from = "", to = "UTF-8", sub = "") %>%
str_replace_all("[^[:print:]]", "") %>%
str_squish()
}
traducir_pais <- function(nombre) {
case_when(
nombre == "Germany" ~ "Alemania",
nombre == "Spain" ~ "España",
nombre == "Canada" ~ "Canadá",
nombre == "Philippines" ~ "Filipinas",
nombre == "Rep. of Korea" ~ "Corea del Sur",
nombre == "Japan" ~ "Japón",
nombre == "Malaysia" ~ "Malasia",
nombre == "Netherlands" ~ "Países Bajos",
nombre %in% c("Türkiye", "T\xfcrkiye") ~ "Turquía",
nombre == "USA" ~ "Estados Unidos",
nombre == "India" ~ "India",
nombre == "Thailand" ~ "Tailandia",
nombre == "Bulgaria" ~ "Bulgaria",
nombre == "Peru" ~ "Perú",
nombre == "Chile" ~ "Chile",
nombre == "Other Asia, nes" ~ "Otros Asia (no especificado)",
TRUE ~ nombre
)
}
data <- read_csv("/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/UN TRADE/FINAL.csv",
locale = locale(encoding = "UTF-8")) %>%
clean_names()
## Warning: One or more parsing issues, call `problems()` on your data frame for details,
## e.g.:
## dat <- vroom(...)
## problems(dat)
## Rows: 12217 Columns: 47
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (19): typeCode, freqCode, reporterISO, reporterDesc, flowCode, flowDesc,...
## dbl (21): refPeriodId, refYear, refMonth, period, reporterCode, partnerCode,...
## lgl (7): isOriginalClassification, isLeaf, isQtyEstimated, isAltQtyEstimate...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
exportaciones_mex <- data %>%
filter(ref_year == 2023,
flow_desc == "Export",
reporter_desc == "Mexico",
cmd_code == 2603,
primary_value > 0,
net_wgt > 0,
!is.na(partner_desc),
partner_desc != "World") %>%
select(destino = partner_desc, valor_total = primary_value)
importaciones_desde_mex <- data %>%
filter(ref_year == 2023,
flow_desc == "Import",
partner_desc == "Mexico",
cmd_code == 2603,
primary_value > 0,
net_wgt > 0,
!is.na(reporter_desc),
reporter_desc != "World") %>%
select(destino = reporter_desc, valor_total = primary_value)
paises_ya_reportados <- unique(exportaciones_mex$destino)
importaciones_filtradas <- importaciones_desde_mex %>%
filter(!(destino %in% paises_ya_reportados))
exportaciones_corregidas <- bind_rows(exportaciones_mex, importaciones_filtradas) %>%
group_by(destino) %>%
summarise(valor_total = sum(valor_total, na.rm = TRUE), .groups = "drop") %>%
mutate(destino = traducir_pais(destino))
total_exportado <- sum(exportaciones_corregidas$valor_total, na.rm = TRUE)
sankey_data <- exportaciones_corregidas %>%
mutate(
origen = "México",
porcentaje = valor_total / total_exportado * 100,
destino_etiqueta = paste0(
destino, " (",
ifelse(porcentaje < 0.1, "<0.1", sprintf("%.1f", porcentaje)),
"%)")
) %>%
mutate(
origen = limpiar_utf8(origen),
destino_etiqueta = limpiar_utf8(destino_etiqueta),
valor_total = as.numeric(valor_total)
)
nombres_nodos <- unique(c(sankey_data$origen, sankey_data$destino_etiqueta))
nodes <- data.frame(name = nombres_nodos) %>%
mutate(name = limpiar_utf8(name))
sankey_data <- sankey_data %>%
mutate(
IDsource = match(origen, nodes$name) - 1,
IDtarget = match(destino_etiqueta, nodes$name) - 1
)
missing_ids <- sankey_data %>% filter(is.na(IDsource) | is.na(IDtarget))
print("Flujos con IDs faltantes:")
## [1] "Flujos con IDs faltantes:"
print(missing_ids)
## # A tibble: 0 × 7
## # ℹ 7 variables: destino <chr>, valor_total <dbl>, origen <chr>,
## # porcentaje <dbl>, destino_etiqueta <chr>, IDsource <dbl>, IDtarget <dbl>
ColourScal <- 'd3.scaleOrdinal().range([
"#9F2241",
"#BC955C",
"#6F7271",
"#235B4E",
"#DDC9A3",
"#414141",
"#7A6F5F",
"#98989A",
"#003E51"
])'
sankeyNetwork(
Links = sankey_data,
Nodes = nodes,
Source = "IDsource",
Target = "IDtarget",
Value = "valor_total",
NodeID = "name",
sinksRight = TRUE,
colourScale = ColourScal,
nodeWidth = 30,
nodePadding = 16,
fontSize = 13,
iterations = 0
)
## Links is a tbl_df. Converting to a plain data frame.
top10_compradores <- exportaciones_corregidas %>%
arrange(desc(valor_total)) %>%
slice(1:10)
top10_compradores
## # A tibble: 10 × 2
## destino valor_total
## <chr> <dbl>
## 1 China 3529760559
## 2 Japón 158682341
## 3 Canadá 140310004.
## 4 España 132938069.
## 5 Filipinas 120989642
## 6 Alemania 82701205.
## 7 Malasia 25976163.
## 8 Corea del Sur 25483007
## 9 Otros Asia (no especificado) 21409922.
## 10 Perú 11943092.
China se consolida como el principal destino de las exportaciones globales de cobre.
China absorbió el 86.2 % de las exportaciones mexicanas de cobre en 2024, lo que representa una concentración comercial sumamente alta hacia un solo país.
Aunque otros mercados como Alemania, España, Canadá y Filipinas participan en menor medida, ningún otro país supera el 5 % del total exportado por México.
Esta dependencia representa tanto una fortaleza comercial por el volumen asegurado, como una vulnerabilidad estratégica ante cualquier disrupción en la demanda o política comercial de China.
A nivel global, México representa aproximadamente el 10 % del total de las importaciones de cobre de China según el flujo observado, siendo superado principalmente por Chile, que aporta más de la mitad del total.
México es un proveedor relevante pero no dominante para el mercado chino, lo que sugiere espacio para mejorar competitividad frente a líderes regionales como Chile y Ecuador.
data <- read_csv("/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/UN TRADE/FINAL.csv",
locale = locale(encoding = "UTF-8")) %>%
clean_names()
## Warning: One or more parsing issues, call `problems()` on your data frame for details,
## e.g.:
## dat <- vroom(...)
## problems(dat)
## Rows: 12217 Columns: 47
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (19): typeCode, freqCode, reporterISO, reporterDesc, flowCode, flowDesc,...
## dbl (21): refPeriodId, refYear, refMonth, period, reporterCode, partnerCode,...
## lgl (7): isOriginalClassification, isLeaf, isQtyEstimated, isAltQtyEstimate...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
importaciones_china <- data %>%
filter(ref_year == 2024,
flow_desc == "Import",
reporter_desc == "China",
cmd_code == 2603,
primary_value > 0,
net_wgt > 0,
!is.na(partner_desc),
partner_desc != "World") %>%
select(origen = partner_desc, valor_total = primary_value)
exportaciones_hacia_china <- data %>%
filter(ref_year == 2024,
flow_desc == "Export",
partner_desc == "China",
cmd_code == 2603,
primary_value > 0,
net_wgt > 0,
!is.na(reporter_desc),
reporter_desc != "World") %>%
select(origen = reporter_desc, valor_total = primary_value)
paises_reportados <- unique(importaciones_china$origen)
exportaciones_no_reportadas <- exportaciones_hacia_china %>%
filter(!(origen %in% paises_reportados))
importaciones_completas <- bind_rows(importaciones_china, exportaciones_no_reportadas) %>%
group_by(origen) %>%
summarise(valor_total = sum(valor_total, na.rm = TRUE), .groups = "drop")
importaciones_completas <- importaciones_completas %>%
mutate(origen = case_when(
origen == "Albania" ~ "Albania",
origen == "Armenia" ~ "Armenia",
origen == "Australia" ~ "Australia",
origen == "Belgium" ~ "Bélgica",
origen == "Bolivia (Plurinational State of)" ~ "Bolivia",
origen == "Brazil" ~ "Brasil",
origen == "Bulgaria" ~ "Bulgaria",
origen == "Canada" ~ "Canadá",
origen == "Chile" ~ "Chile",
origen == "China, Hong Kong SAR" ~ "China, RAE de Hong Kong",
origen == "Dominican Rep." ~ "República Dominicana",
origen == "Ecuador" ~ "Ecuador",
origen == "Georgia" ~ "Georgia",
origen == "Germany" ~ "Alemania",
origen == "India" ~ "India",
origen == "Japan" ~ "Japón",
origen == "Kyrgyzstan" ~ "Kirguistán",
origen == "Malaysia" ~ "Malasia",
origen == "Mexico" ~ "México",
origen == "Namibia" ~ "Namibia",
origen == "Pakistan" ~ "Pakistán",
origen == "Peru" ~ "Perú",
origen == "Philippines" ~ "Filipinas",
origen == "Rep. of Korea" ~ "Corea del Sur",
origen == "Romania" ~ "Rumania",
origen == "South Africa" ~ "Sudáfrica",
origen == "Spain" ~ "España",
origen == "Sweden" ~ "Suecia",
origen == "Switzerland" ~ "Suiza",
origen == "Türkiye" ~ "Turquía",
origen == "USA" ~ "Estados Unidos",
origen == "United Kingdom" ~ "Reino Unido",
origen == "Uzbekistan" ~ "Uzbekistán",
origen == "Zimbabwe" ~ "Zimbabue",
TRUE ~ origen
))
total_importado <- sum(importaciones_completas$valor_total, na.rm = TRUE)
sankey_data <- importaciones_completas %>%
mutate(
destino = "China",
porcentaje = valor_total / total_importado * 100,
origen_etiqueta = paste0(
origen, " (",
ifelse(porcentaje < 0.1, "<0.1", sprintf("%.1f", porcentaje)),
"%)")
)
limpiar_utf8 <- function(x) {
x %>%
iconv(from = "", to = "UTF-8", sub = "") %>%
str_replace_all("[^[:print:]]", "") %>%
str_squish()
}
sankey_data <- sankey_data %>%
mutate(
origen_etiqueta = limpiar_utf8(origen_etiqueta),
destino = limpiar_utf8(destino),
valor_total = as.numeric(valor_total)
)
nombres_nodos <- unique(c(sankey_data$origen_etiqueta, sankey_data$destino))
nodes <- data.frame(name = nombres_nodos) %>%
mutate(name = limpiar_utf8(name))
sankey_data <- sankey_data %>%
mutate(
IDsource = match(origen_etiqueta, nodes$name) - 1,
IDtarget = match(destino, nodes$name) - 1
)
missing_ids <- sankey_data %>% filter(is.na(IDsource) | is.na(IDtarget))
print("Flujos con IDs faltantes:")
## [1] "Flujos con IDs faltantes:"
print(missing_ids)
## # A tibble: 0 × 7
## # ℹ 7 variables: origen <chr>, valor_total <dbl>, destino <chr>,
## # porcentaje <dbl>, origen_etiqueta <chr>, IDsource <dbl>, IDtarget <dbl>
ColourScal <- 'd3.scaleOrdinal().range([
"#9F2241", "#BC955C", "#6F7271", "#235B4E",
"#DDC9A3", "#414141", "#7A6F5F", "#98989A", "#003E51"
])'
sankeyNetwork(
Links = sankey_data,
Nodes = nodes,
Source = "IDsource",
Target = "IDtarget",
Value = "valor_total",
NodeID = "name",
sinksRight = TRUE,
colourScale = ColourScal,
nodeWidth = 30,
nodePadding = 16,
fontSize = 13,
iterations = 0
)
## Links is a tbl_df. Converting to a plain data frame.
top10_proveedores <- importaciones_completas %>%
arrange(desc(valor_total)) %>%
slice(1:10)
top10_proveedores
## # A tibble: 10 × 2
## origen valor_total
## <chr> <dbl>
## 1 "Chile" 21012301030.
## 2 "México" 3718889902
## 3 "Canadá" 2925518772.
## 4 "Ecuador" 2102153539.
## 5 "España" 1865059010.
## 6 "Filipinas" 1038822263
## 7 "Brasil" 827481658
## 8 "Corea del Sur" 684855122
## 9 "T\xfcrkiye" 502890354
## 10 "Estados Unidos" 465469510
Japón ha sido históricamente un comprador relevante de cobre a nivel internacional. Sin embargo, en 2024, su participación como destino de las exportaciones mexicanas de cobre mostró una caída significativa.
En 2023, México exportó aproximadamente 158.7 millones de dólares en cobre hacia Japón. Para 2024, ese valor cayó a 20.6 millones de dólares, lo que representa una disminución del 87 % en términos anuales.
Este descenso coloca a Japón como un destino marginal para las exportaciones mexicanas de cobre, con solo 0.2 % de participación en el total exportado. Esta contracción ocurre en un contexto donde Japón sigue recibiendo cobre de países como Chile (36.7 %), Indonesia (17.1 %), y Perú (12.6 %), lo que indica una mayor dependencia del mercado japonés hacia otros proveedores asiáticos y sudamericanos.
Esta situación plantea retos para México en cuanto a competitividad de precios, calidad de producto o acuerdos comerciales vigentes con Japón. Revertir esta tendencia podría requerir una estrategia específica de reposicionamiento frente a competidores clave en la región Asia-Pacífico.
Es recomendable monitorear las causas de esta caída e identificar oportunidades para reactivar flujos exportadores en ese destino.
data <- read_csv("/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/UN TRADE/FINAL.csv",
locale = locale(encoding = "UTF-8")) %>%
clean_names()
## Warning: One or more parsing issues, call `problems()` on your data frame for details,
## e.g.:
## dat <- vroom(...)
## problems(dat)
## Rows: 12217 Columns: 47
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (19): typeCode, freqCode, reporterISO, reporterDesc, flowCode, flowDesc,...
## dbl (21): refPeriodId, refYear, refMonth, period, reporterCode, partnerCode,...
## lgl (7): isOriginalClassification, isLeaf, isQtyEstimated, isAltQtyEstimate...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
importaciones_japon <- data %>%
filter(ref_year == 2024,
flow_desc == "Import",
reporter_desc == "Japan",
cmd_code == 2603,
primary_value > 0,
net_wgt > 0,
!is.na(partner_desc),
partner_desc != "World") %>%
select(origen = partner_desc, valor_total = primary_value)
exportaciones_hacia_japon <- data %>%
filter(ref_year == 2024,
flow_desc == "Export",
partner_desc == "Japan",
cmd_code == 2603,
primary_value > 0,
net_wgt > 0,
!is.na(reporter_desc),
reporter_desc != "World") %>%
select(origen = reporter_desc, valor_total = primary_value)
paises_reportados <- unique(importaciones_japon$origen)
exportaciones_no_reportadas <- exportaciones_hacia_japon %>%
filter(!(origen %in% paises_reportados))
importaciones_completas <- bind_rows(importaciones_japon, exportaciones_no_reportadas) %>%
group_by(origen) %>%
summarise(valor_total = sum(valor_total, na.rm = TRUE), .groups = "drop")
importaciones_completas <- importaciones_completas %>%
mutate(origen = case_when(
origen == "Australia" ~ "Australia",
origen == "Belgium" ~ "Bélgica",
origen == "Canada" ~ "Canadá",
origen == "Chile" ~ "Chile",
origen == "Congo" ~ "Congo",
origen == "Finland" ~ "Finlandia",
origen == "Indonesia" ~ "Indonesia",
origen == "Mexico" ~ "México",
origen == "Netherlands" ~ "Países Bajos",
origen == "Other Asia, nes" ~ "Otro Asia, ne",
origen == "Papua New Guinea" ~ "Papúa Nueva Guinea",
origen == "Peru" ~ "Perú",
origen == "Philippines" ~ "Filipinas",
origen == "USA" ~ "Estados Unidos",
TRUE ~ origen
))
total_importado <- sum(importaciones_completas$valor_total, na.rm = TRUE)
sankey_data <- importaciones_completas %>%
mutate(
destino = "Japón",
porcentaje = valor_total / total_importado * 100,
origen_etiqueta = paste0(
origen, " (",
ifelse(porcentaje < 0.1, "<0.1", sprintf("%.1f", porcentaje)),
"%)")
)
limpiar_utf8 <- function(x) {
x %>%
iconv(from = "", to = "UTF-8", sub = "") %>%
str_replace_all("[^[:print:]]", "") %>%
str_squish()
}
sankey_data <- sankey_data %>%
mutate(
origen_etiqueta = limpiar_utf8(origen_etiqueta),
destino = limpiar_utf8(destino),
valor_total = as.numeric(valor_total)
)
nombres_nodos <- unique(c(sankey_data$origen_etiqueta, sankey_data$destino))
nodes <- data.frame(name = nombres_nodos) %>%
mutate(name = limpiar_utf8(name))
sankey_data <- sankey_data %>%
mutate(
IDsource = match(origen_etiqueta, nodes$name) - 1,
IDtarget = match(destino, nodes$name) - 1
)
missing_ids <- sankey_data %>% filter(is.na(IDsource) | is.na(IDtarget))
print("Flujos con IDs faltantes:")
## [1] "Flujos con IDs faltantes:"
print(missing_ids)
## # A tibble: 0 × 7
## # ℹ 7 variables: origen <chr>, valor_total <dbl>, destino <chr>,
## # porcentaje <dbl>, origen_etiqueta <chr>, IDsource <dbl>, IDtarget <dbl>
ColourScal <- 'd3.scaleOrdinal().range([
"#9F2241", "#BC955C", "#6F7271", "#235B4E",
"#DDC9A3", "#414141", "#7A6F5F", "#98989A", "#003E51"
])'
sankeyNetwork(
Links = sankey_data,
Nodes = nodes,
Source = "IDsource",
Target = "IDtarget",
Value = "valor_total",
NodeID = "name",
sinksRight = TRUE,
colourScale = ColourScal,
nodeWidth = 30,
nodePadding = 16,
fontSize = 13,
iterations = 0
)
## Links is a tbl_df. Converting to a plain data frame.
top10_proveedores <- importaciones_completas %>%
arrange(desc(valor_total)) %>%
slice(1:10)
top10_proveedores
## # A tibble: 10 × 2
## origen valor_total
## <chr> <dbl>
## 1 Chile 4991429183.
## 2 Indonesia 2319099169.
## 3 Australia 1996585819.
## 4 Perú 1711364110.
## 5 Canadá 875107716.
## 6 Estados Unidos 720835108.
## 7 Papúa Nueva Guinea 568959950.
## 8 Otro Asia, ne 262182057.
## 9 Filipinas 132672867.
## 10 México 20648419.
En 2024, Alemania mostró un notable incremento como destino de las exportaciones mexicanas de cobre. El valor exportado pasó de 82.7 millones de dólares en 2023 a 187.5 millones en 2024, lo que representa un crecimiento del +127 % respecto al año anterior.
Con esta variación, Alemania se posiciona como uno de los principales destinos emergentes para el cobre mexicano, con una participación del 4.3 % del total exportado por México en ese año.
No obstante, al observar el flujo global hacia Alemania, México aún no figura entre los principales proveedores. En 2024, los principales exportadores de cobre hacia Alemania fueron: - Brasil (27.9 %) - Chile (26.7 %) - Australia (11.2 %) - Perú (11.7 %) - Indonesia (6.8 %) - Canadá (7.1 %)
México, con una participación del 3.8 %, se mantiene por debajo de otros competidores regionales y globales.
Se necesita fortalecer relaciones comerciales y aprovechar ventajas logísticas podrían ser factores clave para ampliar la presencia mexicana en este mercado.
data <- read_csv("/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/UN TRADE/FINAL.csv",
locale = locale(encoding = "UTF-8")) %>%
clean_names()
## Warning: One or more parsing issues, call `problems()` on your data frame for details,
## e.g.:
## dat <- vroom(...)
## problems(dat)
## Rows: 12217 Columns: 47
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (19): typeCode, freqCode, reporterISO, reporterDesc, flowCode, flowDesc,...
## dbl (21): refPeriodId, refYear, refMonth, period, reporterCode, partnerCode,...
## lgl (7): isOriginalClassification, isLeaf, isQtyEstimated, isAltQtyEstimate...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
importaciones_alemania <- data %>%
filter(ref_year == 2024,
flow_desc == "Import",
reporter_desc == "Germany",
cmd_code == 2603,
primary_value > 0,
net_wgt > 0,
!is.na(partner_desc),
partner_desc != "World") %>%
select(origen = partner_desc, valor_total = primary_value)
exportaciones_hacia_alemania <- data %>%
filter(ref_year == 2024,
flow_desc == "Export",
partner_desc == "Germany",
cmd_code == 2603,
primary_value > 0,
net_wgt > 0,
!is.na(reporter_desc),
reporter_desc != "World") %>%
select(origen = reporter_desc, valor_total = primary_value)
paises_reportados <- unique(importaciones_alemania$origen)
exportaciones_no_reportadas <- exportaciones_hacia_alemania %>%
filter(!(origen %in% paises_reportados))
importaciones_completas <- bind_rows(importaciones_alemania, exportaciones_no_reportadas) %>%
group_by(origen) %>%
summarise(valor_total = sum(valor_total, na.rm = TRUE), .groups = "drop")
importaciones_completas <- importaciones_completas %>%
mutate(origen = case_when(
origen == "Australia" ~ "Australia",
origen == "Belgium" ~ "Bélgica",
origen == "Bosnia Herzegovina" ~ "Bosnia y Herzegovina",
origen == "Brazil" ~ "Brasil",
origen == "Canada" ~ "Canadá",
origen == "Chile" ~ "Chile",
origen == "Finland" ~ "Finlandia",
origen == "Indonesia" ~ "Indonesia",
origen == "Italy" ~ "Italia",
origen == "Kazakhstan" ~ "Kazajistán",
origen == "Mexico" ~ "México",
origen == "Mongolia" ~ "Mongolia",
origen == "Morocco" ~ "Marruecos",
origen == "Namibia" ~ "Namibia",
origen == "Netherlands" ~ "Países Bajos",
origen == "Norway" ~ "Noruega",
origen == "Peru" ~ "Perú",
origen == "Singapore" ~ "Singapur",
origen == "Spain" ~ "España",
origen == "Sweden" ~ "Suecia",
origen == "Switzerland" ~ "Suiza",
origen == "Türkiye" ~ "Turquía",
origen == "USA" ~ "Estados Unidos",
origen == "United Kingdom" ~ "Reino Unido",
origen == "United Rep. of Tanzania" ~ "Tanzania",
TRUE ~ origen
))
total_importado <- sum(importaciones_completas$valor_total, na.rm = TRUE)
sankey_data <- importaciones_completas %>%
mutate(
destino = "Alemania",
porcentaje = valor_total / total_importado * 100,
origen_etiqueta = paste0(
origen, " (",
ifelse(porcentaje < 0.1, "<0.1", sprintf("%.1f", porcentaje)),
"%)")
)
limpiar_utf8 <- function(x) {
x %>%
iconv(from = "", to = "UTF-8", sub = "") %>%
str_replace_all("[^[:print:]]", "") %>%
str_squish()
}
sankey_data <- sankey_data %>%
mutate(
origen_etiqueta = limpiar_utf8(origen_etiqueta),
destino = limpiar_utf8(destino),
valor_total = as.numeric(valor_total)
)
nombres_nodos <- unique(c(sankey_data$origen_etiqueta, sankey_data$destino))
nodes <- data.frame(name = nombres_nodos) %>%
mutate(name = limpiar_utf8(name))
sankey_data <- sankey_data %>%
mutate(
IDsource = match(origen_etiqueta, nodes$name) - 1,
IDtarget = match(destino, nodes$name) - 1
)
missing_ids <- sankey_data %>% filter(is.na(IDsource) | is.na(IDtarget))
print("Flujos con IDs faltantes:")
## [1] "Flujos con IDs faltantes:"
print(missing_ids)
## # A tibble: 0 × 7
## # ℹ 7 variables: origen <chr>, valor_total <dbl>, destino <chr>,
## # porcentaje <dbl>, origen_etiqueta <chr>, IDsource <dbl>, IDtarget <dbl>
ColourScal <- 'd3.scaleOrdinal().range([
"#9F2241", "#BC955C", "#6F7271", "#235B4E",
"#DDC9A3", "#414141", "#7A6F5F", "#98989A", "#003E51"
])'
sankeyNetwork(
Links = sankey_data,
Nodes = nodes,
Source = "IDsource",
Target = "IDtarget",
Value = "valor_total",
NodeID = "name",
sinksRight = TRUE,
colourScale = ColourScal,
nodeWidth = 30,
nodePadding = 16,
fontSize = 13,
iterations = 0
)
## Links is a tbl_df. Converting to a plain data frame.
top10_proveedores <- importaciones_completas %>%
arrange(desc(valor_total)) %>%
slice(1:10)
top10_proveedores
## # A tibble: 10 × 2
## origen valor_total
## <chr> <dbl>
## 1 Brasil 1387664940.
## 2 Chile 1329915778.
## 3 Perú 583104123.
## 4 Australia 554891734.
## 5 Canadá 353786522.
## 6 Indonesia 340761067.
## 7 México 187510935.
## 8 Singapur 48008875.
## 9 Finlandia 43368669.
## 10 Suecia 40771120.
Se estimó una regresión log–log con efectos fijos por país:
log(cantidad exportada) ~ log(precio unitario FOB) Objetivo Medir cómo reaccionan las exportaciones de cobre ante cambios en el precio, controlando por factores estructurales constantes (como geografía o infraestructura).
Resultado principal Elasticidad estimada: −0.64 → Un aumento del 1 % en el precio reduce 0.64 % el volumen exportado, en promedio, dentro de un mismo país.
Interpretación Este resultado sugiere una respuesta moderadamente inelástica, consistente con rigideces de oferta, capacidad limitada o decisiones estratégicas.
Utilidad del análisis Informa políticas de comercio y fiscalidad.
Evalúa restricciones productivas.
Ayuda a anticipar ingresos ante variaciones de precio.
Conclusión Las exportaciones de cobre reaccionan al precio, pero no proporcionalmente. El modelo permite entender esa dinámica controlando por condiciones estructurales de cada país.
# Data --------------------------------------------------------------------
df <- "/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/UN TRADE/FINAL.csv"
# Cargar el archivo
df <- read_csv("/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/UN TRADE/FINAL.csv") %>%
clean_names()
## Warning: One or more parsing issues, call `problems()` on your data frame for details,
## e.g.:
## dat <- vroom(...)
## problems(dat)
## Rows: 12217 Columns: 47
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (19): typeCode, freqCode, reporterISO, reporterDesc, flowCode, flowDesc,...
## dbl (21): refPeriodId, refYear, refMonth, period, reporterCode, partnerCode,...
## lgl (7): isOriginalClassification, isLeaf, isQtyEstimated, isAltQtyEstimate...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# #Doing fixed effects regression -----------------------------------------
# Filtro: Solo exportaciones de cobre y crear precio unitario
df2 <- df %>%
filter(cmd_code == 2603, # cmd_code 2603 = Copper ores and concentrates
flow_desc == "Export", # solo exportaciones
!is.na(net_wgt),
net_wgt > 0) %>%
mutate(
precio_unitario_fob = primary_value / net_wgt
) %>%
filter(!is.na(precio_unitario_fob), precio_unitario_fob > 0)
# 2. Agregar (colapsar) datos a nivel país–año
df_agregado <- df2 %>%
group_by(reporter_iso, ref_year) %>%
summarise(
# Cantidad total exportada por país y año
net_wgt_total = sum(net_wgt, na.rm = TRUE),
# Precio unitario promedio ponderado por kilos exportados
precio_unitario_prom = sum(net_wgt * precio_unitario_fob, na.rm = TRUE) /
sum(net_wgt, na.rm = TRUE)
) %>%
ungroup()
## `summarise()` has grouped output by 'reporter_iso'. You can override using the
## `.groups` argument.
# 3. Ajustar modelo de efectos fijos (“within”) sobre los datos agregados
model_within_agregado <- plm(
log(net_wgt_total) ~ log(precio_unitario_prom),
data = df_agregado,
index = c("reporter_iso", "ref_year"),
model = "within"
)
# 4. Mostrar resumen del modelo corregido
summary(model_within_agregado)
## Oneway (individual) effect Within Model
##
## Call:
## plm(formula = log(net_wgt_total) ~ log(precio_unitario_prom),
## data = df_agregado, model = "within", index = c("reporter_iso",
## "ref_year"))
##
## Unbalanced Panel: n = 101, T = 1-7, N = 510
##
## Residuals:
## Min. 1st Qu. Median 3rd Qu. Max.
## -11.546063 -0.358012 0.044294 0.605670 6.443883
##
## Coefficients:
## Estimate Std. Error t-value Pr(>|t|)
## log(precio_unitario_prom) -0.643806 0.096979 -6.6386 1.012e-10 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Total Sum of Squares: 1955.9
## Residual Sum of Squares: 1765.2
## R-Squared: 0.097487
## Adj. R-Squared: -0.12593
## F-statistic: 44.0712 on 1 and 408 DF, p-value: 1.0117e-10
df_etiquetas <- df_agregado %>%
group_by(reporter_iso) %>%
slice_max(order_by = net_wgt_total, n = 1) %>%
ungroup()
ggplot(df_agregado, aes(x = log(precio_unitario_prom),
y = log(net_wgt_total),
color = as.factor(ref_year))) +
geom_point(alpha = 0.6, size = 3) +
geom_smooth(method = "lm", se = FALSE, color = "black", linetype = "dashed") +
geom_text_repel(data = df_etiquetas,
aes(label = reporter_iso),
size = 3,
show.legend = FALSE) +
scale_color_viridis_d(option = "C") +
labs(
title = "Relación log–log entre precio unitario y cantidad exportada",
subtitle = "Exportaciones de cobre (mayor volumen por país)",
x = "Log(Precio unitario FOB promedio)",
y = "Log(Peso neto total exportado)",
color = "Año"
) +
theme_ipsum() +
theme(legend.position = "bottom")
## `geom_smooth()` using formula = 'y ~ x'
## Warning: ggrepel: 60 unlabeled data points (too many overlaps). Consider
## increasing max.overlaps
Se estimaron modelos log–log por país exportador para analizar cómo reaccionan las exportaciones al precio unitario FOB:
log(peso neto) ~ log(precio unitario FOB) Cada coeficiente representa la elasticidad-precio: si el valor es alto en magnitud, las exportaciones responden fuertemente a cambios de precio.
Resultados clave Promedio global: −0.64 → sensibilidad moderada a los precios.
México: −1.4 → alta elasticidad. Un alza del 1 % en precio reduce 1.4 % el volumen exportado.
Chile: −0.92 → también sensible, pero menos que México.
Interpretación económica La respuesta varía entre países según factores como:
Capacidad exportadora
Costos logísticos
Contratos comerciales
Estrategias de política o control estatal
Utilidad del análisis Detecta países más o menos sensibles al precio.
Ayuda a diseñar políticas de precios y promoción exportadora.
Permite evaluar riesgos frente a mercados volátiles.
data <- "/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/UN TRADE/ExportsL.csv"
data <- read_csv("/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/UN TRADE/Exports.csv") %>%
clean_names() %>%
mutate(valor_unitario_fob_calculado = primary_value / net_wgt) %>%
filter(
flow_desc == "Export",
partner_iso != 'W00',
!is.na(valor_unitario_fob_calculado),
net_wgt > 0,
partner2iso == 'W00') %>%
with_groups(
.groups = reporter_iso,
mutate,
n = n()
) %>%
filter(n > 5) %>%
group_by(reporter_iso) %>%
nest()
## Warning: One or more parsing issues, call `problems()` on your data frame for details,
## e.g.:
## dat <- vroom(...)
## problems(dat)
## Rows: 7102 Columns: 47
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (19): typeCode, freqCode, reporterISO, reporterDesc, flowCode, flowDesc,...
## dbl (21): refPeriodId, refYear, refMonth, period, reporterCode, partnerCode,...
## lgl (7): isOriginalClassification, isLeaf, isQtyEstimated, isAltQtyEstimate...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
imports_lm <- function(data){
lm(log(net_wgt) ~ log(valor_unitario_fob_calculado),
data = data)
}
data_imports_nested <- data |>
mutate(
model = map(data, imports_lm),
model_tidy = map(model, ~ if (is.logical(.x)) NA else tidy(.x)),
model_glance = map(model, ~ if (is.logical(.x)) NA else glance(.x))
)
data_imports_m <- data_imports_nested |>
unnest(model_tidy)
data_imports_m %>%
filter(term == "log(valor_unitario_fob_calculado)") %>%
ggplot(aes(x = estimate)) +
geom_histogram() +
geom_vline(xintercept = data_imports_m %>%
filter(reporter_iso == 'MEX', term == "log(valor_unitario_fob_calculado)") %>%
pull(estimate)
)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
coef_global <- -0.643806
coef_data <- data_imports_m %>%
filter(term == "log(valor_unitario_fob_calculado)")
coef_mex <- coef_data %>% filter(reporter_iso == "MEX") %>% pull(estimate)
coef_chl <- coef_data %>% filter(reporter_iso == "CHL") %>% pull(estimate)
ggplot(coef_data, aes(x = estimate)) +
geom_histogram(fill = "skyblue", color = "white", bins = 30) +
geom_vline(xintercept = coef_global, linetype = "dashed", color = "black", size = 1) +
annotate("text", x = coef_global + 0.05, y = 15,
label = paste0("Promedio global (", round(coef_global, 2), ")"),
angle = 0, hjust = 0, color = "black", fontface = "italic") +
geom_vline(xintercept = coef_mex, color = "red", size = 1.2) +
annotate("text", x = coef_mex - 0.05, y = 13,
label = paste0("México (", round(coef_mex, 2), ")"),
angle = 0, hjust = 1, color = "red", fontface = "bold") +
geom_vline(xintercept = coef_chl, color = "blue", size = 1.2) +
annotate("text", x = coef_chl + 0.05, y = 11,
label = paste0("Chile (", round(coef_chl, 2), ")"),
angle = 0, hjust = 0, color = "blue", fontface = "bold") +
scale_x_continuous(breaks = seq(-6, 10, by = 2)) +
labs(
title = "Distribución de coeficientes por país",
subtitle = "Modelo log–log: log(peso neto) ~ log(precio unitario FOB)",
x = "Coeficiente estimado (elasticidad)",
y = "Número de países"
) +
theme_minimal()
Para priorizar mercados estratégicos, se construyó un semáforo de elasticidad precio de las exportaciones, clasificando a los países según qué tanto baja su demanda cuando sube el precio del cobre:
Esta clasificación se basó en un modelo econométrico que estima cómo varía la cantidad demandada cuando se incrementa el precio unitario FOB en las exportaciones mexicanas de cobre (fuente: UN Comtrade + modelo propio).
En ese contexto:
Japón debe ser una prioridad para recuperar relaciones comerciales, ya que ha dejado de comprar cobre mexicano, probablemente por su alta sensibilidad al precio. Se sugiere evaluar mecanismos para ofrecer precios más competitivos y condiciones que agreguen valor (como logística eficiente o acuerdos preferenciales).
Alemania, que en 2024 se convirtió en el segundo socio comercial de México, representa una gran oportunidad. Su comportamiento inelástico sugiere que se pueden negociar precios más altos sin comprometer el volumen exportado, además de fortalecer relaciones de largo plazo.
# Semaforo ----------------------------------------------------------------------
library(tidyverse)
library(sf)
library(janitor)
# Conlclusioón
coef_data <- coef_data %>%
mutate(
clasificacion = case_when(
estimate > -0.5 ~ "Inelástica", # Casi no reaccionan al precio
estimate <= -0.5 & estimate >= -1 ~ "Elasticidad media",
estimate < -1 ~ "Elástica" # Reaccionan fuertemente al precio
)
)
# 1. Leer shapefile mundial
world <- st_read("/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/world") %>%
clean_names()
## Reading layer `world-administrative-boundaries' from data source
## `/Users/alanplacidoherrera/Documents/R con Alan/RET0/Data/world'
## using driver `ESRI Shapefile'
## Simple feature collection with 256 features and 8 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: -180 ymin: -58.49861 xmax: 180 ymax: 83.6236
## Geodetic CRS: WGS 84
# 2. Asegúrate de tener `coef_data` con la columna 'clasificacion' ya creada
# Ya lo hiciste, así que solo seguimos
# 3. Unir shapefile con datos de elasticidad por código ISO
world_elasticidad <- world %>%
left_join(coef_data, by = c("iso3" = "reporter_iso"))
# 4. Mapa
ggplot(world_elasticidad) +
geom_sf(aes(fill = clasificacion), color = "gray90", size = 0.1) +
scale_fill_manual(
name = "Elasticidad precio",
values = c(
"Inelástica" = "#2ECC71", # verde
"Elasticidad media" = "#F1C40F", # amarillo
"Elástica" = "#E74C3C" # rojo
)
) +
labs(
title = "Riesgo Comercial por Elasticidad Precio de las Exportaciones",
subtitle = "Clasificación de países según sensibilidad al precio del cobre",
caption = "Fuente: UN Comtrade + modelo propio"
) +
theme_minimal(base_family = "Helvetica") +
theme(
plot.title = element_text(size = 16, face = "bold"),
plot.subtitle = element_text(size = 12),
legend.position = "bottom"
)
# Diccionario de traducción ISO → nombre en español
traduccion_iso <- c(
"KOR" = "Corea del Sur", "CHL" = "Chile", "ECU" = "Ecuador", "CHE" = "Suiza", "TUR" = "Turquía",
"BOL" = "Bolivia", "LAO" = "Laos", "GBR" = "Reino Unido", "DOM" = "República Dominicana",
"RUS" = "Rusia", "ESP" = "España", "KEN" = "Kenia", "OMN" = "Omán", "FRA" = "Francia",
"ITA" = "Italia", "PNG" = "Papúa Nueva Guinea", "POL" = "Polonia", "THA" = "Tailandia",
"ZAF" = "Sudáfrica", "ARE" = "Emiratos Árabes Unidos", "MEX" = "México", "NLD" = "Países Bajos",
"HKG" = "Hong Kong", "MRT" = "Mauritania", "BGR" = "Bulgaria", "TZA" = "Tanzania",
"SGP" = "Singapur", "GTM" = "Guatemala", "USA" = "Estados Unidos", "CHN" = "China",
"MAR" = "Marruecos", "ZMB" = "Zambia", "BEL" = "Bélgica", "MYS" = "Malasia",
"ZWE" = "Zimbabue", "UZB" = "Uzbekistán", "SAU" = "Arabia Saudita", "DEU" = "Alemania",
"NGA" = "Nigeria", "PHL" = "Filipinas", "BRA" = "Brasil", "AUS" = "Australia",
"NER" = "Níger", "NAM" = "Namibia", "SWE" = "Suecia", "IRN" = "Irán", "KAZ" = "Kazajistán",
"FIN" = "Finlandia", "PAK" = "Pakistán", "PER" = "Perú", "ROU" = "Rumania",
"PAN" = "Panamá", "AZE" = "Azerbaiyán", "ETH" = "Etiopía", "COD" = "R. D. del Congo",
"IRL" = "Irlanda", "IND" = "India", "CAN" = "Canadá", "ARM" = "Armenia", "BWA" = "Botsuana",
"KGZ" = "Kirguistán", "GEO" = "Georgia", "PRT" = "Portugal", "MKD" = "Macedonia",
"SRB" = "Serbia", "COL" = "Colombia", "MNG" = "Mongolia", "IDN" = "Indonesia",
"TJK" = "Tayikistán", "S19" = "Otros"
)
# Crear df_semaforo con nombres traducidos
df_semaforo <- coef_data %>%
select(reporter_iso, estimate, clasificacion) %>%
mutate(pais_espanol = recode(reporter_iso, !!!traduccion_iso)) %>%
arrange(clasificacion, estimate)
# Mostrar tabla ordenada en consola
print(df_semaforo, n = Inf)
## # A tibble: 71 × 4
## # Groups: reporter_iso [71]
## reporter_iso estimate clasificacion pais_espanol
## <chr> <dbl> <chr> <chr>
## 1 S19 -0.998 Elasticidad media Otros
## 2 KOR -0.958 Elasticidad media Corea del Sur
## 3 CHL -0.919 Elasticidad media Chile
## 4 ECU -0.883 Elasticidad media Ecuador
## 5 CHE -0.848 Elasticidad media Suiza
## 6 TUR -0.807 Elasticidad media Turquía
## 7 BOL -0.707 Elasticidad media Bolivia
## 8 LAO -0.677 Elasticidad media Laos
## 9 GBR -0.636 Elasticidad media Reino Unido
## 10 DOM -5.61 Elástica República Dominicana
## 11 TJK -3.87 Elástica Tayikistán
## 12 RUS -3.50 Elástica Rusia
## 13 ESP -3.11 Elástica España
## 14 KEN -2.37 Elástica Kenia
## 15 OMN -2.11 Elástica Omán
## 16 COG -2.03 Elástica COG
## 17 FRA -1.80 Elástica Francia
## 18 ITA -1.75 Elástica Italia
## 19 PNG -1.68 Elástica Papúa Nueva Guinea
## 20 POL -1.49 Elástica Polonia
## 21 THA -1.47 Elástica Tailandia
## 22 ZAF -1.43 Elástica Sudáfrica
## 23 ARE -1.41 Elástica Emiratos Árabes Unidos
## 24 MEX -1.40 Elástica México
## 25 NLD -1.38 Elástica Países Bajos
## 26 HKG -1.26 Elástica Hong Kong
## 27 MRT -1.23 Elástica Mauritania
## 28 BGR -1.21 Elástica Bulgaria
## 29 TZA -1.20 Elástica Tanzania
## 30 SGP -1.18 Elástica Singapur
## 31 GTM -1.10 Elástica Guatemala
## 32 USA -1.04 Elástica Estados Unidos
## 33 CHN -1.02 Elástica China
## 34 MAR -0.444 Inelástica Marruecos
## 35 ZMB -0.423 Inelástica Zambia
## 36 BEL -0.416 Inelástica Bélgica
## 37 MYS -0.326 Inelástica Malasia
## 38 ZWE -0.311 Inelástica Zimbabue
## 39 UZB -0.309 Inelástica Uzbekistán
## 40 SAU -0.149 Inelástica Arabia Saudita
## 41 DEU -0.134 Inelástica Alemania
## 42 NGA -0.109 Inelástica Nigeria
## 43 PHL -0.0119 Inelástica Filipinas
## 44 BRA 0.0970 Inelástica Brasil
## 45 AUS 0.229 Inelástica Australia
## 46 NER 0.241 Inelástica Níger
## 47 NAM 0.405 Inelástica Namibia
## 48 SWE 0.408 Inelástica Suecia
## 49 IRN 0.426 Inelástica Irán
## 50 KAZ 0.521 Inelástica Kazajistán
## 51 FIN 0.702 Inelástica Finlandia
## 52 PAK 0.937 Inelástica Pakistán
## 53 PER 0.952 Inelástica Perú
## 54 ROU 0.972 Inelástica Rumania
## 55 PAN 1.01 Inelástica Panamá
## 56 AZE 1.02 Inelástica Azerbaiyán
## 57 ETH 1.44 Inelástica Etiopía
## 58 COD 1.54 Inelástica R. D. del Congo
## 59 IRL 1.56 Inelástica Irlanda
## 60 IND 1.59 Inelástica India
## 61 CAN 1.90 Inelástica Canadá
## 62 ARM 2.43 Inelástica Armenia
## 63 BWA 2.69 Inelástica Botsuana
## 64 KGZ 2.73 Inelástica Kirguistán
## 65 GEO 2.94 Inelástica Georgia
## 66 PRT 3.16 Inelástica Portugal
## 67 MKD 3.74 Inelástica Macedonia
## 68 SRB 4.02 Inelástica Serbia
## 69 COL 6.37 Inelástica Colombia
## 70 MNG 7.89 Inelástica Mongolia
## 71 IDN 8.95 Inelástica Indonesia