Visualización del flujo comercial en mapas de Python – Parte I: Mapas de flujo comercial bidireccional

Visualización del flujo comercial en mapas de Python – Parte I: Mapas de flujo comercial bidireccional

El intercambio de bienes y servicios a cambio de sus valores correspondientes es una parte intrincada de nuestra vida diaria. De manera similar, los países entablan diferentes tipos de relaciones comerciales para el intercambio de productos y servicios como electricidad, productos energéticos, materias primas, bienes procesados, turismo, etc. Comprender el flujo comercial entre países (importación y exportación) es crucial para evaluar el los ingresos y gastos de un país, la destreza económica, la seguridad del suministro y la naturaleza de la relación entre los países.

En esta serie de dos partes, voy a compartir cómo se puede visualizar el flujo comercial entre países en mapas usando Python. La primera parte de esta serie se centrará en visualizar la flujo comercial bidireccional (importaciones y exportaciones) entre países. La segunda parte se centrará en visualizar la flujo comercial neto entre países. Voy a utilizar conjuntos de datos ficticios de un producto hipotético para esta visualización. Destacaré mi país y región (Nepal/Asia del Sur) como ejemplo a efectos de demostración. Empecemos.

Foto por Mapas GeoJango en desempaquetar

Encontrar coordenadas de flechas

En los mapas de flujo comercial, mi objetivo era representar las relaciones comerciales bidireccionales entre países. Por ejemplo, la exportación de Nepal a la India estaría representada por la primera flecha (A1-A2) y la importación de Nepal desde la India estaría representada por una segunda flecha (A3-A4). De esta manera, cada relación de par de países requeriría cuatro puntos de coordenadas para definir los puntos inicial y final de las flechas para representar las exportaciones y las importaciones respectivamente.

Si bien también es posible asumir una coordenada que se puede detectar automáticamente (por ejemplo, el centroide de la geometría de un país), mi intención era marcar los puntos en un mapa y obtener sus coordenadas individualmente. Para ello, es posible crear un proyecto en una aplicación como Google Earth, exportar un archivo KML y extraer las coordenadas con un conversor (por ejemplo, el conversor de datos GIS de la web de Nube de mis geodatos).

Keyhole Markup Language (KML) es un formato de archivo utilizado para mostrar datos geográficos en una aplicación como Google Earth. Utiliza una estructura basada en etiquetas con elementos y atributos anidados y se basa en el estándar XML (Google, 2023).

Datos

La estructura de mis datos de entrada se ve como se muestra en la imagen a continuación. Contiene cinco relaciones comerciales diferentes entre países vecinos: Nepal-India, Nepal-Bangladesh, Nepal-China, India-Pakistán e India-Sri Lanka. Para cada par de países, hay cuatro puntos de coordenadas para los puntos inicial y final de las dos flechas. El Valor1 representa la exportación del País1 al País2. Valor2 representa la importación del País1 desde el País2. El objetivo es mostrar esta relación en un mapa de Python.

Entrada de datos para mapas de flujos comerciales. Imagen del autor.

Leí los datos anteriores como un marco de datos de pandas df. Además, creé objetos de diccionario como transferencias que contienen el volumen de exportación e importación entre cada par de países, y startarrow1_dict que contiene la coordenada del punto de partida de la primera flecha.

Creando los objetos de diccionario necesarios. Imagen del autor.

Descripción del código

En esta sección, describiré el código utilizado para visualizar los mapas de flujo comercial. Utilizaré principalmente los paquetes matplotlib y cartopy. También he usado los mismos paquetes para visualizar la anomalía de la temperatura global de la superficie en uno de mis publicaciones anteriores.

  1. Importar paquetes requeridos

Comencé importando los principales paquetes y dependencias requeridos como se muestra a continuación:

import cartopy.crs as ccrs
import cartopy.io.shapereader as shpreader

import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib import colormaps
from matplotlib.colors import Normalize
from matplotlib.cm import ScalarMappable

import numpy as np
import pandas as pd
import os

2. Lea el archivo de forma

Como archivo de forma, utilicé Natural Earth. Vector. El archivo vectorial puede ser leído directamente por el lector de formas. módulo del paquete cartopy.

# get the country border file (10m resolution) and extract
shpfilename = shpreader.natural_earth(
resolution=”10m”,
category=”cultural”,
name=”admin_0_countries”,
)
reader = shpreader.Reader(shpfilename)
countries = reader.records()

Usando un paquete llamado Fiona, es posible leer la lista de todos los países como se muestra a continuación.

El paquete Fiona se utiliza para abrir el archivo de forma y extraer la lista de todos los nombres de países. Imagen del autor.

3. Extraiga la información solo de los países requeridos.

A continuación, creé requerido, que es una lista de seis países que tienen relaciones comerciales. También creé un objeto de diccionario c, que contenía FionaRecord, es decir, toda la información relevante de los países que se puede utilizar para trazar.

# required countries
required = [“Nepal”, “India”, “Bangladesh”,”China”,”Pakistan”,”Sri Lanka”]

# extract the specific country information
c = {
co.attributes["ADMIN"]: co
for co in countries if co.attributes["ADMIN"] in required
}

4. Trazar el países requeridos y recorte

En este paso, primero, tracé las geometrías de los países requeridos en una proyección PlateCarree como se muestra a continuación:

Trazar los países requeridos. Imagen del autor.

A continuación, quería recortar las geometrías del resto del mundo para poder tener una vista ampliada solo de los seis países. Determiné la extensión de los valores máximo y mínimo de longitud y latitud respectivamente que podrían cubrir los seis países, establecí la extensión para el gráfico de ejes y tracé los países. En el bucle for, también agregué un código que mostraría los nombres de los países sobre la geometría del centroide de cada país.

el orden atributo del paquete matplotlib determinaría el orden de dibujo de los artistas. Los artistas con orden z más alto se dibujan en la parte superior.

# get overall boundary box from country bounds
extents = np.array([c[cn].bounds for cn in c])
lon = [extents.min(0)[0], extents.max(0)[2]]
lat = [extents.min(0)[1], extents.max(0)[3]]

ax = plt.axes(projection=ccrs.PlateCarree())

# get country centroids
ax.set_extent([lon[0] - 1, lon[1] + 1, lat[0] - 1, lat[1] + 1])

for key, cn in zip(c.keys(),c.values()):
ax.add_geometries(cn.geometry,
crs=ccrs.PlateCarree(),
edgecolor="gray",
facecolor="whitesmoke",
zorder = 1)

# Add country names
centroid = cn.geometry.centroid

ax.text(
centroid.x,
centroid.y,
key, # Assuming 'name' is the attribute containing the country names
horizontalalignment='center',
verticalalignment='center',
transform=ccrs.PlateCarree(),
fontsize=8, # Adjust the font size as needed
color='black', # Set the color of the text
zorder = 2
)


plt.axis("off")
plt.show()

5. Configure el mapa de colores, agregue parches de flechas y una barra de colores.

Esta es la sección más importante del código. Primero, seleccioné viridis_r, es decir, la paleta de colores inversa de viridis como mi mapa de colores. A continuación, determiné el valor mínimo y máximo de cualquier valor comercial entre países como tmin y tmax respectivamente. Estos valores se normalizan de modo que tmin corresponda al extremo más bajo (0) y tmax corresponda al extremo más alto (1) del mapa de colores cmap y se utilicen en consecuencia en el código siguiente.

Luego recorrí las transferencias y usé el FancyArrowParche objeto para trazar las flechas entre países. Cada objeto de flecha está asociado con una columna de color única que representa el flujo comercial de un país a otro. Si bien también es posible utilizar un desplazamiento de las coordenadas de la primera flecha para trazar la segunda flecha, he especificado las coordenadas para la segunda flecha en mi código. En el código, el atributo de escala de mutación se usa para controlar la longitud de la punta de la flecha y el atributo de ancho de línea se usa para controlar el ancho de la línea principal.

Finalmente, agregué la barra de colores horizontal debajo del gráfico principal.

ax = plt.axes(projection=ccrs.PlateCarree())

# get country centroids
ax.set_extent([lon[0] - 1, lon[1] + 1, lat[0] - 1, lat[1] + 1])

for key, cn in zip(c.keys(),c.values()):
ax.add_geometries(cn.geometry,
crs=ccrs.PlateCarree(),
edgecolor="grey",
facecolor="whitesmoke",
zorder = 1)

# Add country names
centroid = cn.geometry.centroid

ax.text(
centroid.x,
centroid.y,
key, # Assuming 'name' is the attribute containing the country names
horizontalalignment='center',
verticalalignment='center',
transform=ccrs.PlateCarree(),
fontsize=8, # Adjust the font size as needed
color='black', # Set the color of the text
zorder = 2
)

# set up a colormap
cmap = colormaps.get("viridis_r")
tmin = np.array([v for v in transfers.values()]).min()
tmax = np.array([v for v in transfers.values()]).max()
norm = Normalize(tmin, tmax)

for tr in transfers:
c1, c2 = tr.split(",")
startarrow1 = startarrow1_dict[tr]
endarrow1 = endarrow1_dict[tr]

startarrow2 = startarrow2_dict[tr]
endarrow2 = endarrow2_dict[tr]


t1 = transfers[tr][0]
col = cmap(norm(t1))

# Use the arrow function to draw arrows
arrow = mpatches.FancyArrowPatch(
(startarrow1[0], startarrow1[1]),
(endarrow1[0], endarrow1[1]),
mutation_scale=20, #control the length of head of arrow
color=col,
arrowstyle='-|>',
linewidth=2, # You can adjust the linewidth to control the arrow body width
zorder = 3
)
ax.add_patch(arrow)

#OTHER WAY
offset = 1
t2 = transfers[tr][1]
col = cmap(norm(t2))
arrow = mpatches.FancyArrowPatch(
(startarrow2[0], startarrow2[1]),
(endarrow2[0], endarrow2[1]),
mutation_scale=20,
color=col,
arrowstyle='-|>',
linewidth=2, # You can adjust the linewidth to control the arrow body width
zorder = 4
)
ax.add_patch(arrow)

sm = ScalarMappable(norm, cmap)
fig = plt.gcf()
cbar = fig.colorbar(sm, ax=ax,
orientation = "horizontal",
pad = 0.05, #distance between main plot and colorbar
shrink = 0.8, #control length
aspect = 20 #control width
)
cbar.set_label("Trade flow")

plt.title("Trade flow in South Asia")
plt.axis("off")

plt.savefig("trade_flow2_with_labels.jpeg",
dpi = 300)
plt.show()

El producto final se muestra a continuación. En mi conjunto de datos ficticio, el menor flujo comercial es la exportación de Sri Lanka a la India (53 unidades), que está representada por el color amarillo. El mayor flujo comercial es la exportación de Bangladesh a Nepal (98 unidades), que está representada por el color violeta.

Flujo comercial bidireccional entre países representado por flechas entre países. Imagen del autor.

Conclusión

En esta publicación, demostré cómo el flujo comercial entre países, incluidas las relaciones de exportación e importación, se puede visualizar en un mapa de Python usando dos flechas. He utilizado los paquetes cartopy y matplotlib para este propósito. En la segunda parte de esta serie, mostraré cómo se puede visualizar la relación del flujo comercial “neto” y al mismo tiempo destacaré a los países exportadores netos e importadores netos.

El cuaderno de esta publicación está disponible en este GitHub. repositorio. ¡Gracias por leer!

Referencias

Desarrolladores de Google, 2023. Tutorial KML | Lenguaje de marcado de ojo de cerradura | Google para desarrolladores. El contenido de esta página está bajo licencia bajo la Licencia Creative Commons Atribución 4.0


Visualización del flujo comercial en mapas de Python – Parte I: Mapas de flujo comercial bidireccional fue publicado originalmente en Hacia la ciencia de datos en Medium, donde las personas continúan la conversación resaltando y respondiendo a esta historia.