
Nelle mappe dei flussi commerciali, ho mirato a rappresentare le relazioni commerciali bidirezionali tra i paesi. Ad esempio, l’esportazione dal Nepal all’India sarebbe rappresentata dalla prima freccia (A1-A2) e l’importazione dal Nepal dall’India sarebbe rappresentata da una seconda freccia (A3-A4). In questo modo, ciascuna relazione di coppia di paesi richiederebbe quattro punti di coordinate per definire i punti iniziale e finale delle frecce per rappresentare rispettivamente le esportazioni e le importazioni.
Sebbene sia anche possibile assumere una coordinata che possa essere rilevata automaticamente (ad esempio, il baricentro della geometria di un paese), intendevo contrassegnare i punti su una mappa e ottenere le loro coordinate individualmente. A questo scopo è possibile creare un progetto in un’applicazione come Google Earth, esportare un file KML ed estrarre le coordinate con un convertitore (ad esempio il convertitore di dati GIS nel sito web di MyGeodata Cloud).
Keyhole Markup Language (KML) è un formato di file utilizzato per visualizzare dati geografici in un’applicazione come Google Earth. Utilizza una struttura basata su tag con elementi e attributi annidati e si basa sullo standard XML (Google, 2023).
La struttura dei miei dati di input appare come mostrata nell’immagine qui sotto. Contiene cinque diverse relazioni commerciali tra i paesi vicini: Nepal-India, Nepal-Bangladesh, Nepal-Cina, India-Pakistan e India-Sri Lanka. Per ogni coppia di paesi, ci sono quattro punti di coordinate per i punti iniziale e finale delle due frecce. Valore1 rappresenta l’esportazione dal Paese1 al Paese2. Valore2 rappresenta l’importazione per Paese1 da Paese2. Lo scopo è visualizzare questa relazione in una mappa Python.
Ho letto i dati di cui sopra come un dataframe panda df
. Inoltre, ho creato oggetti dizionario come transfers
contenente il volume delle esportazioni e delle importazioni tra ciascuna coppia di paesi, e startarrow1_dict
contenente le coordinate del punto iniziale della prima freccia.
In questa sezione descriverò il codice utilizzato per visualizzare le mappe dei flussi commerciali. Utilizzerò principalmente i pacchetti matplotlib e cartopy. Ho anche utilizzato gli stessi pacchetti per visualizzare l’anomalia della temperatura superficiale globale in uno dei miei post precedenti.
- Importa i pacchetti richiesti
Ho iniziato importando i principali pacchetti e dipendenze richiesti come mostrato di seguito:
import cartopy.crs as ccrs
import cartopy.io.shapereader as shpreaderimport 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. Leggi il file di forma
Come file di forma, ho utilizzato Natural Earth Vettore. Il file vettoriale può essere letto direttamente dallo shapereader modulo del pacchetto cartopico.
# 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()
Utilizzando un pacchetto chiamato Fiona, è possibile leggere l’elenco di tutti i paesi come mostrato di seguito.
3. Estrarre le informazioni solo sui paesi richiesti
Successivamente, ho creato required
che è un elenco di sei paesi che hanno relazioni commerciali. Ho anche creato un oggetto dizionario c
che conteneva il FionaRecord, cioè tutte le informazioni rilevanti dei paesi che possono essere utilizzate per il tracciamento.
# 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. Traccia il required
paesi e ritaglio
In questo passaggio, innanzitutto, ho tracciato le geometrie di required
paesi in una proiezione PlateCarree come mostrato di seguito:
Successivamente, ho voluto ritagliare le geometrie del resto del mondo in modo da poter avere una visione ingrandita solo dei sei paesi. Ho determinato rispettivamente l’estensione dei valori massimi e minimi di longitudine e latitudine che potrebbero coprire tutti e sei i paesi, ho impostato l’estensione del grafico degli assi e ho tracciato i paesi. Nel ciclo for ho anche aggiunto un codice che visualizzasse i nomi dei paesi sulla geometria del baricentro di ciascun paese.
IL zorder
attributo del pacchetto matplotlib determinerebbe l’ordine di disegno degli artisti. Artisti con più alto zorder
sono disegnati in alto.
# 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. Imposta la mappa dei colori, aggiungi le patch delle frecce e la barra dei colori.
Questa è la sezione più importante del codice. Per prima cosa ho selezionato viridis_r
cioè, la tavolozza dei colori inversa di viridis
come la mia mappa dei colori. Successivamente, ho determinato il valore minimo e massimo di qualsiasi valore commerciale tra paesi tmin
E tmax
rispettivamente. Questi valori sono normalizzati in modo tale che tmin
corrisponde all’estremità più bassa (0) e tmax
corrisponde all’estremità più alta (1) della mappa dei colori cmap
e utilizzato di conseguenza nel codice successivo.
Poi ho eseguito il looping del file transfers
e utilizzato il FancyArrowPatch oggetto per tracciare le frecce tra i paesi. Ogni oggetto freccia è associato a un colore univoco col
che rappresenta il flusso commerciale da un paese all’altro. Sebbene sia anche possibile utilizzare un offset dalle coordinate della prima freccia per tracciare la seconda freccia, nel mio codice ho specificato le coordinate per la seconda freccia. Nel codice, il mutation_scale
l’attributo viene utilizzato per controllare la lunghezza della punta della freccia e l’attributo linewidth
l’attributo viene utilizzato per controllare la larghezza della linea principale.
Infine, ho aggiunto la barra dei colori orizzontale sotto la trama principale.
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()
Il prodotto finale è mostrato di seguito. Nel mio set di dati fittizio, il flusso commerciale minimo è l’esportazione dallo Sri Lanka all’India (53 unità), rappresentato dal colore giallo. Il flusso commerciale più elevato è l’esportazione dal Bangladesh al Nepal (98 unità), rappresentato dal colore viola.
In questo post, ho dimostrato come il flusso commerciale tra paesi, comprese le relazioni di esportazione e importazione, possa essere visualizzato in una mappa Python utilizzando due frecce. A questo scopo ho utilizzato i pacchetti cartopy e matplotlib. Nella seconda parte di questa serie, mostrerò come visualizzare la relazione del flusso commerciale “netto”, evidenziando i paesi esportatori netti e importatori netti.
Il notebook per questo post è disponibile in questo GitHub deposito. Grazie per aver letto!
Riferimenti
Sviluppatori Google, 2023. Esercitazione KML | Linguaggio di markup Keyhole | Google per gli sviluppatori. Il contenuto di questa pagina è concesso in licenza con il Licenza Creative Commons Attribuzione 4.0
Fonte: towardsdatascience.com