Press "Enter" to skip to content

用Python地图可视化贸易流程-第一部分:双向贸易流程地图

商品和服务的交换,以其相应的价值为代价,是我们日常生活中的重要组成部分。同样,各国之间展开不同类型的贸易关系,以交换产品和服务,如电力、能源商品、原材料、加工商品、旅游等。了解国家之间的贸易流动(进口和出口)对评估一个国家的收益和支出、经济实力、供应安全以及国家间关系的性质至关重要。

在这个两部分系列中,我将分享如何通过Python将国家之间的贸易流动可视化为地图。这个系列的第一部分将重点介绍可视化国家之间的双向(进口和出口)贸易流动。第二部分将重点介绍国家之间的净贸易流动。我将使用一个假设产品的虚拟数据集来进行可视化。我将以我的国家和地区(尼泊尔/南亚)作为示例进行演示。让我们开始吧。

Photo by GeoJango Maps on Unsplash

查找箭头的坐标

在贸易流动地图中,我旨在表示国家之间的双向贸易关系。例如,从尼泊尔到印度的出口将由第一箭头(A1-A2)表示,尼泊尔从印度进口将由第二箭头(A3-A4)表示。这样,每个国家对的关系都需要四个坐标点来定义箭头的起点和终点,分别表示出口和进口。

虽然也可以假定可以自动检测到一个坐标(例如,一个国家几何的质心),但我打算在地图上标注出这些点并逐个获取它们的坐标。为此,可以在应用程序,如Google Earth中创建一个项目,导出一个KML文件,并使用转换器(例如,MyGeodata Cloud网站中的GIS数据转换器)提取坐标。

Keyhole Markup Language(KML)是一种文件格式,用于在诸如Google Earth之类的应用程序中显示地理数据。它使用基于标记的结构,具有嵌套元素和属性,并基于XML标准(Google,2023年)。

数据

我的输入数据的结构如下图所示。它包含相邻国家之间的五种不同贸易关系:尼泊尔-印度、尼泊尔-孟加拉国、尼泊尔-中国、印度-巴基斯坦和印度-斯里兰卡。对于每个国家对,有四个坐标点表示两个箭头的起点和终点。Value1表示从国家1到国家2的出口,Value2表示国家1从国家2的进口。目的是在Python地图中显示这种关系。

Data input for trade flow maps. Image by Author.

我将上述数据读取为一个pandas dataframe df。此外,我创建了字典对象,例如transfers,其中包含每个国家对之间的出口和进口量,以及startarrow1_dict,其中包含第一箭头起点的坐标。

Creating necessary dictionary objects. Image by Author.

代码说明

在这个部分,我将描述用于可视化贸易流地图的代码。我主要使用matplotlib和cartopy包。我还在我之前的帖子中使用了相同的包来可视化全球地表温度异常情况。

  1. 导入所需包

我首先导入所需的主要包和依赖项,如下所示:

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. 读取形状文件

我使用了自然地球矢量作为形状文件。该矢量文件可以直接由cartopy包的shapereader模块读取。

# 获取国家边界文件(10m分辨率)并提取shp文件名 = shpreader.natural_earth(
                            resolution="10m",
                            category="cultural",
                            name="admin_0_countries",
                            )
reader = shpreader.Reader(shpfilename)
countries = reader.records()

使用一个名为Fiona的包,可以读取所有国家的列表,如下所示。

Fiona软件包用于打开形状文件并提取所有国家名称列表。作者提供的图像。

3. 提取所需国家的信息

接下来,我创建了一个名为required的六个国家的列表,这些国家之间有贸易关系。我还创建了一个字典对象c,其中包含FionaRecord即可用于绘制的所有国家的相关信息。

# 所需的国家required = ["尼泊尔", "印度", "孟加拉国", "中国", "巴基斯坦", "斯里兰卡"]# 提取特定国家的信息c = { co.attributes["ADMIN"]: co for co in countries if co.attributes["ADMIN"] in required }

4. 绘制 required 国家并剪辑

在此步骤中,首先,在PlateCarree投影中绘制了所需国家的几何图形,如下所示:

绘制所需国家。作者提供的图像。

接下来,我想剪切掉其余世界的几何图形,以便我只能看到这六个国家的放大视图。我确定了能够覆盖所有六个国家的最大和最小经度和纬度值的范围,设置了坐标轴绘图的范围,并绘制了这些国家。在for循环中,我还添加了一个代码,可以在每个国家的质心几何图形上显示国家名称。

matplotlib包的zorder属性确定了绘图对象的绘制顺序。具有更高zorder的对象将绘制在顶部。

# 从国家边界获取整个边界框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())# 获取国家质心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)        # 添加国家名称    centroid = cn.geometry.centroid        ax.text(        centroid.x,        centroid.y,        key,  # 假设'name'是包含国家名称的属性        horizontalalignment='center',        verticalalignment='center',        transform=ccrs.PlateCarree(),        fontsize=8,  # 根据需要调整字体大小        color='black',  # 设置文本颜色        zorder = 2        )  plt.axis("off")plt.show()

5. 设置colormap,添加箭头补丁和颜色条

这是代码中最重要的部分。首先,我选择viridis_r,即viridis的反转颜色调色板作为我的colormap。接下来,我确定了任何两个国家之间的贸易值的最小值和最大值,分别为tmintmax。这些值经过归一化处理,使得tmin对应于colormap cmap 的最低端(0),tmax对应于最高端(1),然后在后续代码中使用。

然后,我循环遍历transfers,使用FancyArrowPatch对象绘制国家之间的箭头。每个箭头对象都与一个表示从一个国家到另一个国家的贸易流量的唯一颜色col相关联。虽然可以使用与第一个箭头坐标的偏移来绘制第二个箭头,但在我的代码中,我指定了第二个箭头的坐标。在代码中,mutation_scale属性用于控制箭头头部的长度,linewidth属性用于控制主线的宽度。

最后,我在主绘图下方添加了水平颜色条。

ax = plt.axes(projection=ccrs.PlateCarree())# 获取国家中心点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)        # 添加国家名称    centroid = cn.geometry.centroid        ax.text(        centroid.x,        centroid.y,        key,  # 假设'name'是包含国家名称的属性        horizontalalignment='center',        verticalalignment='center',        transform=ccrs.PlateCarree(),        fontsize=8,  # 根据需要调整字体大小        color='black',  # 设置文本颜色        zorder = 2       )# 设置colormapcmap = 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))        # 使用箭头函数绘制箭头    arrow = mpatches.FancyArrowPatch(        (startarrow1[0], startarrow1[1]),        (endarrow1[0], endarrow1[1]),        mutation_scale=20,    # 控制箭头头部的长度         color=col,        arrowstyle='-|>',        linewidth=2,  # 可以调整linewidth来控制箭头主体的宽度        zorder = 3    )    ax.add_patch(arrow)        #其他方法    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,  # 可以调整linewidth来控制箭头主体的宽度        zorder = 4    )    ax.add_patch(arrow)    sm = ScalarMappable(norm, cmap)fig = plt.gcf()cbar = fig.colorbar(sm, ax=ax,            orientation = "horizontal",            pad = 0.05,  # 主图和颜色条之间的距离            shrink = 0.8, # 控制长度            aspect = 20  # 控制宽度            )cbar.set_label("贸易流量")plt.title("南亚地区的贸易流量")plt.axis("off")plt.savefig("trade_flow2_with_labels.jpeg",           dpi = 300)plt.show()

下面是最终产品的展示。在我的虚拟数据集中,从斯里兰卡到印度的最小贸易流量是出口(53个单位),用黄色表示。从孟加拉国到尼泊尔的最大贸易流量是出口(98个单位),用紫色表示。

两国之间用箭头表示的双向贸易流量。图片作者:作者。

结论

在这篇文章中,我演示了如何使用两个箭头在Python地图中可视化国家之间的贸易流量,包括出口和进口关系。我使用了cartopy和matplotlib软件包来实现这个目的。在这个系列的第二部分中,我将展示如何可视化“净”贸易流量关系,同时突出净出口国和净进口国。

本文的笔记本在GitHub的存储库中可用。感谢您的阅读!

参考文献

Google开发者,2023年。 KML教程 | Keyhole Markup Language | Google for Developers。本页面的内容采用知识共享署名4.0许可

Leave a Reply

Your email address will not be published. Required fields are marked *