基于Python实现大规模光栅人口数据可视化

译者 | 朱先忠
审校 | 重楼
我经常看到网上流传着美丽的人口地图;然而,我也常常会遇到一些技术问题,比如可视化本文中显示的其他的地图片段,或者将大规模光栅数据转换为更便于计算的向量格式 。在本文中,我将通过两个主要全球人口数据来源的实践来尝试克服这其中的一些问题 。

基于Python实现大规模光栅人口数据可视化

文章插图
另一方面,同样要注意,除了它们的美学价值外,显示它们的人口数据和地图是人们可以为任何城市发展或位置智能任务收集和整合的最基本和有价值的信息之一 。它们在规划新设施、选址和集水区分析、估计城市产品规模或分析不同社区等实践应用中特别有用 。
1.数据来源在本文试验中,我将依赖以下两个细粒度的人口估计数据源,您可以通过所附链接来下载这些文件:
  • 欧盟委员会的GHSL(全球人类住区层:https://ghsl.jrc.ec.europa.eu/ghs_pop2019.php)——用于测量每个网格单元的人口水平 。从该数据源中可以找到整体描述以及我在他们2023年的报告中使用的空间分辨率为100米的特定集合 。
  • WorldPop中心 。我将以德国为例 , 使用分辨率为100米的受限条件下的独立国家数据集 。你可以在链接https://hub.worldpop.org/geodata/listing?id=78处查找到完整的国家列表数据,还可以在链接https://hub.worldpop.org/geodata/summary?id=49789处查找到德国数据 。
2.可视化全球人类住区层2.1.导入数据我第一次看到这个数据集是在“体系结构性能”部分的Datashader教程处 。在复制了他们的可视化结果之后,在将其扩展到全球地图时我遇到了一些麻烦,这些问题促使我开展了本文有关的研究工作 。所以,接下来我将向您展示我是如何找到破解上述难题的解决方案的!
首先,我使用xarray包来解析光栅文件,代码如下:
import rioxarrayfile_path = "GHS_POP_E2030_GLOBE_R2023A_54009_100_V1_0/GHS_POP_E2030_GLOBE_R2023A_54009_100_V1_0.tif" data_array = rioxarray.open_rasterio(file_path, chunks=True, lock=False)data_array此代码片断的输出结果是对数据集的一段详细描述:
基于Python实现大规模光栅人口数据可视化

文章插图
2.2.可视化数据段我们已经看到 , 对于大多数标准笔记本电脑来说 , 这是一个非常具有挑战性的数据量 。无论如何 , 让我们试着使用Datashader来可视化数据,这是一个非常方便的工具 , 适用于这种规模的地理空间数据集的展示:
#警告:此处代码块很可能会导致您的计算机内存溢出错误import datashader as dsimport xarray as xrfrom colorcet import palettefrom datashader import transfer_functions as tf# 准备绘图data_array_p = xr.DataArray(data_array)[0]data_array_p = data_array_p.where(data_array_p > 0)data_array_p = data_array_p.compute()#取得图像尺寸信息size = 1200asp = data_array_p.shape[0] / data_array_p.shape[1]#创建数据着色器画布cvs = ds.Canvas(plot_width=size, plot_height=int(asp*size))raster = cvs.raster(data_array_p)#绘制图像cmap = palette["fire"]img = tf.shade(raster, how="eq_hist", cmap=cmap)img虽然这段代码在技术上看起来还可以,但我的2021款带有16GB RAM的M1 macbook Pro出现了一个糟糕的内存溢出错误 。因此,让我们裁剪一下图像以便查看数据!为此 , 我关注上述数据源的“体系结构性能”部分 , 并专注于欧洲数据 , 这是我暂时关注的内容,因为这样的选择确实有效 。
然而,我稍后要回答的主要问题是,尽管内存有限,但我们如何在使用本地机器的情况下可视化整个地球的数据呢?请先等一等!
import datashader as dsimport xarray as xrfrom colorcet import palettefrom datashader import transfer_functions as tfimport numpy as np# 裁剪数据阵列data_array_c = data_array.rio.clip_box(minx=-1_000_000.0, miny=4_250_000.0, maxx=2_500_000.0, maxy=7_750_000.0)data_array_c = xr.DataArray(data_array_c)# 准备绘图data_array_c = xr.DataArray(data_array_c)[0]data_array_c = data_array_c.where(data_array_c > 0)data_array_c = data_array_c.compute()data_array_c = np.flip(data_array_c, 0)# 获取图像大小size = 1200asp = data_array_c.shape[0] / data_array_c.shape[1]# 创建数据着色器画布cvs = ds.Canvas(plot_width=size, plot_height=int(asp*size))raster = cvs.raster(data_array_c)#绘制图像cmap = palette["fire"]img = tf.shade(raster, how="eq_hist", cmap=cmap)img = tf.set_background(img, "black")img


推荐阅读