
本文总结了用Python的basemap模块画图的一些知识点,首发于微信公众号。 整理/撰写: 是Hu不是Who 校稿/排版: 迷途兄 测试环境 : Python版本 3.7.3 / 操作系统windows 7 64位 / 编辑器PyCharm
1 前言
地理信息可视化是我们测绘、气象、地球科学方向的学子常会面对的任务。一副好图胜过大段的文字,可以直观揭示事物的特点,帮助我们探索问题的本质。高质量的成图也可以提高我们科研论文和工作报告的表现力,提高文章的档次。
表1中对笔者和周围朋友常用的地球科学绘图软件做了简单的汇总和对比。一般来说,Excel成图美观度较差,难以通过脚本完成自动化操作,主要用于快速的数据分析。因此,用于地理信息可视化的软件主要是GMT、Matplotlib的basemap模块,和Matlab的M_map模块。

GMT和M_map笔者早先使用过,目前笔者使用的是Python的basemap模块。除了功能强大,语法简单、清晰,轻量级(安装包占用空间不大)等优势之外,另一个主要原因在于Python强大的生态和活跃的社区。无论是数据处理、分析,还是科学计算,日常工作自动化等方面,Python都有丰富且热门的模块。笔者使用Python作为主要开发语言之一,因此就选择了basemap模块,将其集成在数据处理和分析任务中。
笔者周围不少小伙伴对basemap画图很感兴趣。本文根据小伙伴们对basemap模块关心的一些问题,收集资料,结合笔者的一些初步经验,对basemap画图做了初步总结,供大家参考。
文章全文约6000字,包括15个代码(片段),21幅样例图。受篇幅所限,部分较长的代码并未在文中全部贴出。如果您有兴趣,可在后台留言"Python-basemap"和您的邮箱地址,笔者会将本期PDF文稿和相应数据、脚本发送给您。
2 简介
在数据可视化过程中,我们需要将数据在地图上画出来。 比如说我们在地图上画出城市人口,飞机航线,军事基地,矿藏分布等等。这样的地理绘图有助于读者理解空间相关的信息。basemap 是Python的一个强大的负责实现地理信息可视化的库,是Matplotlib的一个附加工具包,通过结合 matplotlib 可以绘制出很多漂亮的地图。
basemap包括GSSH海岸线数据集,以及来自GMT的河流、州和国家边界的数据集。这些数据集可用于在地图上以几种不同的分辨率绘制海岸线,河流和政治边界。basemap底层使用了Geometry Engine-Open Source(GEOS)库,用来将海岸线和边界特征剪切到所需的地图投影区域。此外,basemap还提供读取shapefile的功能。
basemap面向地球科学家的需求,特别是海洋学家和气象学家。起初,杰夫·惠特克(Jeff Whitaker)写“底图”(basemap)用来帮助他进行气候和天气预报的研究。到现在,basemap 不断被开发扩展已经具备了很多功能。多年来,basemap的功能随着各个学科(如生物学,地质学和地球物理学)的科学家的要求和贡献的新功能而演变。
3 关于安装
问1:basemap模块的大小和安装的难易程度?
答:basemap模块约为120M左右,其依赖库pyproj约为20M左右。
由于basemap还没有pip检索,因此传统的(pip install basemap)安装方法不适用。
Windows用户需要到https://www.lfd.uci.edu/~gohlke/pythonlibs/下载对应的wheel文件到本地,然后控制台进入其所在目录,使用pip install xxxx.whl文件安装。其依赖于pyproj库。具体安装过程参考https://zhuanlan.zhihu.com/p/34509847 。Linux用户安装步骤可参考 https://matplotlib.org/basemap/users/installing.html ,包括下载源码、安装GEOS库、设置GEOS_DIR环境变量等步骤,安装完成后可进入到examples文件夹,运行测试例子。 此外还可以通过Anaconda的Python发行版安装。
建议同时安装Pillow库, 可用于以更多不同格式保存图片文件,以及调用bluemarble()
, etopo()
, shadedrelief()
and warpimage()
函数。
问2:basemap使用是否方便?有没有相关介绍或例子?
答:basemap基于GEOS的地图二维数据,其底图数据库与GMT相同,封装了大量常用的地图投影、坐标转换功能,利用简洁的Python语法支持绘出多种多样的地理地图。
如下所示,basemap的功能有且不限于绘制地图、等高线、降水量图、海平面气压天气图、晨昏线等,具体功能及对应实例代码可参考https://matplotlib.org/basemap/users/examples.html。本文后续内容也给出了多个样例。

4 基本操作
问3:能否在地图上画线、画箭头之类的标注线?
答:可以。比如需要连接地图上已知经纬度(lat1,lon1;lat2,lon2)的两个点,可使用plot来进行连线,basemap中暂没有画箭头的函数,可用plt.arrow绘制箭头。一些更高级的用法,比如画球面距离,可使用drawgreatcircle函数。下图实例为绘制伦敦到纽约的直线以及球面距离。

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np
fig=plt.figure()
ax=fig.add_axes([0.1,0.1,0.8,0.8])
mymap = Basemap(llcrnrlon=-100.,llcrnrlat=20.,urcrnrlon=20.,urcrnrlat=60.,
rsphere=(6378137.00,6356752.3142),
resolution='l',projection='merc',
lat_0=40.,lon_0=-20.,lat_ts=20.)
# nylat, nylon are lat/lon of New York
nylat = 40.78; nylon = -73.98
# lonlat, lonlon are lat/lon of London.
lonlat = 51.53; lonlon = 0.08
mymap.drawgreatcircle(nylon,nylat,lonlon,lonlat,linewidth=2,color='b')
mymap.plot([nylon,lonlon],[nylat,lonlat],linewidth=2,color='r',latlon='True')
mymap.drawcoastlines()
mymap.fillcontinents()
mymap.drawparallels(np.arange(10,90,20),labels=[1,1,0,1])
mymap.drawmeridians(np.arange(-180,180,30),labels=[1,1,0,1])
plt.show()
问4:如何导出矢量图?
答:使用函数savefig(),保存矢量图只需要三个参数,即文件名fname,DPI和文件格式format。比如保存文件名为“vectorgraph”,dpi为600,eps格式的图形,可使用如下代码。目前savefig支持的格式包括:eps,jpeg,jpg,pdf,pgf,png,ps,raw,rgba,svg,svgz,tif,tiff。值得注意的是,如果文件名含后缀,则format参数可省略。
fig.savefig('vectorgraph',dpi=600,format='eps')