最近帮一位做平流层研究的同行处理数据图,他提了一嘴:“要是能有一张像Nature文章那样的北半球投影图就好了,看起来特别专业。”我理解他的意思——就是那种圆盘状、以北极点为中心的极地投影地图,上面叠加涡度场、气温异常或者海冰浓度,配合简洁的配色,一眼就能看出高纬地区的空间格局。这类图在气候动力学、海冰监测、大气化学等方向几乎是标配。
但要放在几年前,画这么一张图并不轻松。底图数据要下载,投影要手写参数,海岸线要单独处理,网格线要自己算,整套流程下来没半天搞不定。现在我告诉你,用Python生态里成熟的绘图库,核心绘图代码完全可以控制在十几行以内,出图质量直接对标Nature正文配图的审美标准。这篇文章把整个流程拆开讲清楚,从投影原理到每个参数含义,再到实际画图过程中踩过的坑,一并交代明白,适合正在写论文、准备投稿,或者单纯想把地图画得好看点的科研人。
1. 先把方案定下来:Python绘图生态怎么选
1.1 为什么现在是Python + Cartopy的组合
地图绘制这件事,Python生态里有过不少方案,最古老的是Matplotlib自带的Basemap工具包,当年也是主流,但Basemap在2020年左右停止维护了,官方明确建议用户迁移到Cartopy。如果你现在搜教程还会看到大量Basemap的老代码,我的建议是直接忽略,不要在新项目里用,原因很简单:Basemap基于的地理数据格式比较陈旧,和现代NetCDF、GRIB数据的配合不太顺畅,而且它的投影方式使用起来确实麻烦。
Cartopy是英国气象办公室主导开发的地理空间可视化库,它的底层依赖Shapely和PyKEA,核心优势是做了大量矢量空间计算,比如裁剪、变换、叠加,同时无缝对接Matplotlib的绘图接口。说白了,Cartopy在设计思路上就是“让地理数据画起来像普通数据一样简单”,它把投影变换、海岸线加载、网格线生成这些通通封装成几个函数调用,这是它能做到“几行代码出一张图”的根本原因。
我不是说其他语言没有好方案,比如R语言的ggplot2加sf包也能画,JavaScript有Leaflet和D3,但如果你的研究数据本身就是Python生态里处理的,比如用Xarray读NetCDF、用Pandas做表格、用NumPy算统计量,那用Cartopy画图是衔接成本最低的路径,数据变量名直接拿来就用。
1.2 北极投影图的核心思路:理解两套坐标系
画一张北半球的极地投影图,最绕不开的概念是坐标系。我见过不少新手在这一步卡住,其实搞清楚以后很简单。
Cartopy里有两套坐标系在同时工作:一套是你数据的坐标系,另一套是地图展示的坐标系。比如你的气温数据是0.25度乘0.25度的规则网格,对应的就是等距圆柱投影,Cartopy里叫PlateCarree(你可以在很多代码里看到这个名称),这套坐标下经度从-180到180,纬度从-90到90,像个长方形展开的世界地图。另一套是你最终呈现的坐标系,也就是以北极点为中心的方位角投影,Cartopy里叫NorthPolarStereo,这套坐标下纬线变成同心圆,经线从圆心向四周发散。
你可能会觉得:“既然展示效果是圆的,那我直接把数据按极地投影读进来不就行了吗?”实际上不行,因为你的数据源文件本身并没有采用极地投影网格,绝大多数再分析资料都是规则经纬网格,所以你必须先把数据放在PlateCarree坐标系里,然后让Cartopy去做从“经纬网格坐标”到“投影平面坐标”的数学变换,这个过程是自动的,你只需要在建图时指定projection参数,在绘图时指定transform参数,Cartopy就能正确地把数据“投影”到圆盘上。
1.3 数据准备:画地图需要哪些素材
画图之前先把底图数据搞定。Cartopy内置了一些矢量数据接口,最常见的是Natural Earth数据集,安装Cartopy时会自动下载到本地缓存目录里。这些数据包括海岸线、国界线、湖泊、河流等,对大多数科研论文的配图来说,Natural Earth的分辨率已经足够。
我的建议是使用“50m”分辨率级别的数据,它对应中等细节程度,既不会像“110m”那样粗糙到丢失细节,也不会像“10m”那样文件太大导致每次画图都卡顿。如果你需要更细节的海岸线,比如要画某个海峡或群岛,可以额外从Natural Earth官网下载10m分辨率的数据,然后用Cartopy的shp文件读取接口加载进来,这个后面在实操部分会说。
另外一个重要的数据库是ETOPO地形数据或者叫Global Land One-km Base Elevation,有时候你想要在底图上叠加地形着色,或者把海洋深度表现得更丰富,这时候光靠海岸线矢量就不够了,需要用栅格地形数据。但就Nature风格简洁的插图来说,真的不需要地形面面俱到,淡色陆地加白色海洋已经是主流审美。
2. 实操:从环境配置到第一张圆盘图
2.1 安装依赖:三分钟搞定
先解决环境问题。我建议你用conda创建独立环境,尽量避免在base环境里装一堆地理库,因为Cartopy的二进制依赖(特别是GEOS、PROJ)版本比较敏感,直接用pip有时候会编译报错。用conda装最稳妥:
conda create -n geo python=3.10 conda activate geo conda install -c conda-forge cartopy matplotlib numpy xarray netcdf4如果你平时还需要读GRIB格式的气象数据,可以再加一个“cfgrib”库,但这里暂时用不上。装完之后可以快速验证一下:
import cartopy import matplotlib.pyplot as plt print(cartopy.__version__)如果正常输出版本号,说明安装成功。第一次调用cartopy时它可能会自动下载一些底图数据,需要稍微等待片刻,这个过程会在后台完成,之后再用就不需要了。
2.2 最核心的三行代码:投影、范围、底图
安装好依赖以后,第一张北半球圆盘图其实只需要三行核心代码:
import matplotlib.pyplot as plt import cartopy.crs as ccrs import cartopy.feature as cfeature fig = plt.figure(figsize=(6, 6)) ax = plt.axes(projection=ccrs.NorthPolarStereo()) ax.set_extent([-180, 180, 50, 90], crs=ccrs.PlateCarree()) ax.add_feature(cfeature.LAND, facecolor='#e0e0e0') ax.add_feature(cfeature.OCEAN, facecolor='white') ax.coastlines(linewidth=0.4, color='#333333') plt.savefig('north_polar_test.png', dpi=300, bbox_inches='tight')就这一段,你已经得到一张以北极点为中心的圆盘底图了。但别急着高兴,你得明白这三行里面每一行的真正含义,否则后面调参数时会抓瞎。
ccrs.NorthPolarStereo()定义的是正射视角下的北极极地方位投影,以北极点作为投影中心,默认的中央经线是0度,也就是说0度经线在圆盘上指向正下方,这通常符合大多数人的阅读习惯,不过也可以调整中央经线让地图旋转到更适合你的研究区域的方向。
ax.set_extent([-180, 180, 50, 90], crs=ccrs.PlateCarree())这一行设置的是地图可视范围。注意它需要指定坐标参考系,也就是说“-180到180经度、50到90纬度”这四个边界值是在经纬度坐标下定义的,Cartopy会帮你把这个矩形范围转换到极地投影坐标系下,然后裁剪出对应的区域。这个边界设置在后面的进阶操作里非常有讲究,因为如果你把纬度下限设得太低,比如设成0度,那画出来的就是一大张半球图,北极圈反而只占了一小块,视觉重心就散掉了。对绝大多数北半球研究来说,50度这个纬度线作为圆盘的下边缘比较合适,既能涵盖欧洲、亚洲、北美大部分高纬区域,又能让圆盘内部信息不至于太拥挤。
ax.add_feature(cfeature.LAND, facecolor='#e0e0e0')这一行是给陆地填充灰色,ax.coastlines()是画海岸线轮廓。这里我特意把海洋设为白色,因为后面叠加数据后,变量的暖色调会比较突兀,白色海洋能提供足够对比度。
2.3 添加经纬网格:让数值有坐标感
有了陆地轮廓,加上经纬网格线才是一张完整的科学地图。Cartopy里网格线的用法很直接:
gl = ax.gridlines(draw_labels=True, linewidth=0.3, color='gray', alpha=0.5, linestyle='--') gl.top_labels = False gl.left_labels = True gl.right_labels = False gl.xlabel_style = {'size': 8, 'color': '#333333'} gl.ylabel_style = {'size': 8, 'color': '#333333'}这里有个容易忽略的细节:极地投影下,纬线是同心圆,经线是从中心发散出去的放射线。Cartopy的网格线会自动根据投影方式调整绘制方向,所以你在代码里不需要手动算经纬线的位置,只需要指定画线的样式和标签样式即可。
但我实测下来,Cartopy的gridlines在极地投影下存在一个小问题,默认情况下经度标签会沿圆盘边缘排列,如果中央经线设置不当,标签可能重叠在一起,导致图面很乱。一个稳妥的解决方式是设置gl.rotate_labels = False,同时用gl.xlocator手动控制经线标注的间隔,比如每30度标注一次,可以显著降低重叠概率:
import matplotlib.ticker as mticker gl.xlocator = mticker.FixedLocator([-180, -150, -120, -90, -60, -30, 0, 30, 60, 90, 120, 150])另外一个更好的方案是完全不依赖Cartopy的自动标签,而是手动在特定位置写文本标注经度值。这种方法很绕弯,但效果更可控,Nature期刊上许多图就是这么干的,因为自动标签的样式难免有程序化的僵硬感,手动标注可以配合字体、色彩做出更协调的排版。
2.4 叠加变量场:把数据画上去
底图就绪后,叠加变量是重头戏。以常见的温度异常场为例,如果你用Xarray读入NetCDF数据,画图其实就两步:
import xarray as xr import numpy as np import matplotlib.pyplot as plt import cartopy.crs as ccrs ds = xr.open_dataset('temperature_anomaly.nc') temp = ds['t2m'] - 273.15 # 转摄氏度 fig = plt.figure(figsize=(6, 6)) ax = plt.axes(projection=ccrs.NorthPolarStereo()) ax.set_extent([-180, 180, 50, 90], crs=ccrs.PlateCarree()) cf = ax.contourf(temp.longitude, temp.latitude, temp, transform=ccrs.PlateCarree(), cmap='RdBu_r', levels=21, extend='both') plt.colorbar(cf, orientation='horizontal', shrink=0.7, pad=0.05)这里最关键的参数是transform=ccrs.PlateCarree(),它明确告诉Cartopy:数据本身是经纬网格坐标,但地图显示是极地投影坐标,两者之间需要做插值和变换。如果你漏掉这个参数,数据会被默认当作已经在投影坐标系里,直接导致错位、拉伸,画出来跟变形了一样。
contourf适合画连续场,比如气温、气压、高度场。如果你要画点位数据,比如观测站点,可以改用scatter,同样需要指定transform参数。如果你要画风场箭头,用barbs或quiver,也要指定transform和x、y的网格坐标。这几个接口的投影逻辑一致,掌握了contourf,其他都是触类旁通。
2.5 出图参数:让排版接近期刊标准
论文插图一般有固定的单栏或双栏宽度要求,所以出图尺寸不能随便定。以Nature系列期刊为例,正文配图的单栏宽度大约8.6厘米,双栏宽度大约17.8厘米,对应的dpi至少要300起步,600更保险。
我通常的做法是直接在保存时指定尺寸:
fig.set_size_inches(6, 6) # 适用于双栏时期的方形图 plt.savefig('north_polar_final.png', dpi=600, bbox_inches='tight')这里有一个重要经验:如果你的图形不是单纯的方形,而是带有色标、标题等附加组件,保存时加bbox_inches='tight'可以自动去除多余的白边,但也可能会导致最终图形尺寸与预期不完全一致。更稳妥的方法是先创建一个布局,比如用gridspec或subplots预留出colorbar的位置,然后整体控制布局尺寸。
3. 让图面真正“Nature化”的几个细节
3.1 颜色:比你想象的更有讲究
Nature风格的地图之所以耐看,很大程度上是颜色的功劳。那些蓝红渐变、青色到黄色渐变的方案,并不是随手选的。传统Matplotlib的默认配色(比如jet)彩虹色饱和度太高、过渡不均,容易掩盖数据的细微变化,也不利于色盲读者区分。
我推荐几个科研绘图常用的色带:
- 温度异常:
RdBu_r(红蓝反向),零值附近用白色,这条几乎是最安全的方案。 - 降水:
BrBG(棕绿)或cmocean.rain,能体现干湿差异。 - 海冰浓度:
cmocean.ice自带白青渐变,和冰的视觉印象一致。 - 地形高度:
cmocean.topo或terrain,海陆过渡比较自然。
如果你的数据是百分比、浓度等比值型变量,建议用cmocean库里的感知均匀色带,这类色带在设计时做了亮度均匀性处理,避免了某些区域颜色跳跃过大导致的伪结构感。安装cmocean很简单,几行pip就行。我自己画图的经验是,一旦用上感知均匀色带,再回看传统的jet,会明显觉得后者颜色发腻、层次混乱。
还有一点,colorbar的标注字号应该略微小于正文,一般在7到9磅之间,因为插图在排版时会被缩放,字号太大会显得笨重,太小则看不清。同时,把colorbar的方向改成水平,放在图的下方,可以让正方形的地图主体占比更大,整个图的构图更紧凑。
3.2 地图范围与形状控制:从“能看”到“好看”
很多人画出来的北极图边缘是方形的,中间是圆盘,四个角上一片白。严格来说这不难看,但在Nature相关的文章里,更常见的是圆形地图本身作为图的边界,四个角都被裁掉。要实现这种效果,Cartopy从2023年的0.22版本开始提供了set_boundary接口,用法是在画图之前对坐标轴应用一个圆形Path:
import matplotlib.path as mpath import numpy as np theta = np.linspace(0, 2*np.pi, 100) circle_path = mpath.Path(np.column_stack([np.cos(theta), np.sin(theta)])) ax.set_boundary(circle_path, transform=ax.transAxes)这个操作会把绘图区域裁剪成一个完美的圆形,让图形以圆盘形态呈现,四角自动透明。实测下来,这一个小改动对整个图的观感提升非常明显,有一种“专业期刊配图”的即视感。需要注意的版本兼容性问题。我测试过0.21以及更早的版本,有些年代较早的Cartopy版本不支持直接传入Path对象,需要先把圆形转换为Polygon,或者用ax.spines['geo'].set_visible(False)加辅助mask的方式。但这一步在最新版本里已经很顺畅了,所以建议尽量升级到0.22以上。
3.3 字体与排版:影响审稿人第一印象
字体这块最容易被忽略,但恰恰是审稿人一眼能感受到“专业”的细节。我在看稿件时有个经验:只要图里的坐标数字是细小的无衬线体、字体大小统一、数值位数一致,整个图就显得精神;如果字体大小不一、衬线体和非衬线体混用,哪怕数据再好也觉得粗糙。
Matplotlib默认的DejaVu Sans作为英文字体完全够用,但如果你想更贴合Nature出版的风格,可以换成Arial或者Helvetica,这需要额外注册系统字体。中文字体一般很少出现在地图上,如果确需添加中文标注,推荐使用Noto Sans CJK,安装后在Matplotlib里设置字体族即可。
统一字号也是关键。我的习惯是:地图坐标标签8磅,colorbar标签8磅,图例标题和条目8磅,这样保存为dpi 600后,无论是单栏还是双栏排版都清晰。再有一个细节,坐标轴上不要出现尾数多余的零,比如标成“60N”而不是“60.0N”,Cartopy的gridlines有gl.xlabel_style可以用来调整,但更精细的控制可能需要手动标注。
3.4 多子图:一幅画里讲完一个完整故事
不只是单幅地图形状,Nature风格里非常常见的是多组图拼在一起。比如你想展示北半球四个季节的平均气温异常,可以做一个2×2的子图布局,每张子图用相同的投影范围、相同的色标范围,整体上非常整齐。
子图布局里一个比较实用的技巧是让多张图画共享同一个colorbar,这种做法既省空间又避免误解——如果你给每张子图单独设置colorbar,但色标范围不一致,读者很容易误读数据间的差异。共享colorbar的实现很直接:先用fig.add_subplot(1, 2, 1, projection=ccrs.NorthPolarStereo())和(1, 2, 2, ...)创建坐标轴,画完后在figure层面添加colorbar:
fig = plt.figure(figsize=(10, 5)) ax1 = fig.add_subplot(1, 2, 1, projection=ccrs.NorthPolarStereo()) ax2 = fig.add_subplot(1, 2, 2, projection=ccrs.NorthPolarStereo()) # 在两个子图上分别画数据 cf = ax1.contourf(..., vmin=-5, vmax=5, cmap='RdBu_r') ax2.contourf(..., vmin=-5, vmax=5, cmap='RdBu_r') cbar = fig.colorbar(cf, ax=[ax1, ax2], orientation='horizontal', fraction=0.03)注意contourf的vmin和vmax要显式统一,不然哪怕色带相同,范围不同也会导致对比误导。这个“统一量级”的思维在多图对比里特别重要,也是评审人经常审到的细节。
3.5 权重较高的技巧:裁剪海岸线以外的数据
在极地投影图里,数据场往往会大面积覆盖整个圆盘,但如果你只想突出陆地区域,比如画北半球植被指数或地表温度,就需要把海洋部分的数据遮挡成白色。Cartopy里一个高效的做法是用ax.add_feature(cfeature.OCEAN, facecolor='white', zorder=3),把它放在数据层之上,这样海洋区域的颜色会被白色覆盖。不过要注意zorder的顺序,数据绘制在zorder=0或zorder=1,海洋遮罩放在zorder=3,才能正确覆盖。
如果你的数据需要透过海洋显示,但你又不想看到圆圈外的空白,那可以给海洋添加一个浅灰或很浅的蓝色,起到底色作用而不完全遮盖数据,这个取舍看具体的应用场景。我在处理海冰浓度数据时常常会画海洋为白色再加海冰填充,数据本身带着陆地标签也没有关系,直接叠上去就行。
4. 常见报错与问题排查实录
4.1 数据范围对不上:白屏或超出边界
新手最常遇到的一个现象是:图能画出来,但数据没出现在预期位置,要么整幅图空白,要么数据覆盖了半个地球的变形样子。这种问题90%以上出在transform参数上。
我记得有个项目里的同事在画北极涡旋位置图时,因为忘了在scatter里指定transform=ccrs.PlateCarree(),结果站点坐标全被当作投影平面坐标,直接堆到了地图边缘。排查方式很简单,一是检查transform参数是否存在,二是检查数据的经纬度范围是否在绘图区域范围内。如果你只设置set_extent为50到90度,但个别数据点纬度低于50,那数据会被悄悄裁剪掉,不会报错,但图上看不到。
这里分享一个自查技巧:先用一行最简单的代码画一个点,比如在(0, 70)处打一个红色标记,然后运行完整脚本,看这个点是否落在预期的位置上。如果红色标记不在圆盘圆心附近,说明投影变换链路有问题。
4.2 海岸线下载失败或读不到数据
Cartopy第一次添加海岸线时会从Natural Earth服务器下载数据,国内网络环境下经常存在下载超时的问题,导致后面每次运行都报错。这时候可以手动去Natural Earth的github仓库下载对应的shapefile,然后解压到Cartopy的数据目录里。
一个更省心的方案是直接用cfeature.NaturalEarthFeature并指定本地路径:
land = cfeature.NaturalEarthFeature( 'physical', 'land', '50m', edgecolor='k', facecolor=cfeature.COLORS['land']) ax.add_feature(land)如果你的机器完全没有外网,还可以用内网共享的shapefile路径。但说实话,Cartopy内置的Natural Earth数据一年内也变不了几次,提前缓存好就够了。
4.3 经纬网标签重叠
这是极地投影特有的问题。普通地图经纬线横平竖直,标签位置固定,而极地投影下经线汇聚于北极点,标注很容易挤在一起。除了之前说的用FixedLocator控制标注间隔,另一个思路是关掉部分标签,比如把左、右两侧的经度标签只保留一侧,同时在图外用文字注释经纬网的含义,减少视觉噪音。
我自己的偏好是:圆盘图里通常只标纬度在圆盘外缘,经度标注在图外四角或用小的十字箭头标出,这样图面更干净。
4.4 保存后地图变形或白边过大
这个问题出在保存参数和figsize配合不好。bbox_inches='tight'会裁掉多余白边,但也会改变图形比例。如果你需要精确控制打印尺寸,可以先计算figsize,然后用bbox_inches=None(即默认值)保存,另外用pad_inches=0.02控制边距。
还有一点,如果你的圆盘图是用set_boundary裁剪过的,保存成PDF或SVG矢量格式时,裁剪效果也能保留,但某些旧版PDF查看器可能显示异常。对投稿而言,我的建议是同时保存PNG和PDF两个版本,PNG用于快速预览,PDF用于最终排版。
4.5 常见问题速查表
| 现象 | 原因 | 解决办法 |
|---|---|---|
| 数据没出现在预期位置 | 缺少transform=ccrs.PlateCarree() | 在绘图函数中显式指定数据坐标系 |
| 圆盘外四角露出方形白边 | 未对地图边界做圆形裁剪 | 使用ax.set_boundary(circle_path) |
| 经度标签重叠严重 | 网格线自动标注位置不合理 | 用FixedLocator控制经线标注间隔 |
| 海岸线加载失败 | 首次使用时网络下载中断 | 手动下载shapefile并配置本地数据路径 |
| 多子图颜色不一致 | 各子图vmin/vmax未统一 | 统一设置contourf的范围与色带 |
| 圆盘边缘发白模糊 | 保存dpi过低或绘图窗口未刷新 | 提高dpi至300以上,先fig.canvas.draw() |
5. 更进一步:从“能画出”到“画得专业”的进阶技巧
5.1 添加研究区域高亮与标记
在Nature风格地图中,高亮研究区域是很有用的手段。比如你要分析某个特定区域(北欧或白令海),可以在圆盘图上添加一个基于经纬度坐标的矩形或圆形区域:
import cartopy.geodesic as geodesic # 经纬度坐标下的矩形区域 lons = [-20, 30] lats = [60, 72] ax.add_patch(plt.Rectangle((lons[0], lats[0]), lons[1] - lons[0], lats[1] - lats[0], transform=ccrs.PlateCarree(), facecolor='none', edgecolor='red', linewidth=2))注意矩形依然需要transform参数。用ax.add_patch时,Cartopy能自动把你给的矩形坐标用投影方式转换到极地投影空间里,但有个前提是矩形边缘要沿着经纬线方向,如果你的研究区域不规则,可以改用Polygon给定顶点。
5.2 叠加矢量与流场
北半球极地区域最常见的矢量图是风场或海冰漂移矢量。Cartopy绘制风场的bash很简单:
ax.barbs(lon, lat, u, v, transform=ccrs.PlateCarree(), length=5, sizes={'empty': 0.2}, linewidth=0.4)这里也有一个容易栽的坑:极地投影下,矢量方向的定义会因为投影变化而变得复杂,Cartopy用transform参数自动处理了大部分情况,但如果你的数据分辨率太粗(比如2.5度网格),画出来的barbs可能会稀疏到难以阅读。一个常见的优化是先做插值加密网格,或者用quiver的regrid功能来控制箭头密度。我一般选择自己用scipy.interpolate.griddata插值到0.5度网格再画。
5.3 多面板图排版:如何在一页里讲清楚几个图
一篇论文里,地图常常只是其中的一个panel,你需要把它和其他曲线图、统计箱线图放在一起。这时就有了排版问题。Cartopy自带投影的坐标轴可以和其他普通坐标轴混合使用,但需要注意布局:
fig = plt.figure(figsize=(10, 4)) gs = fig.add_gridspec(1, 3, width_ratios=[1, 1, 0.9]) ax_map = fig.add_subplot(gs[0, 0], projection=ccrs.NorthPolarStereo()) ax_ts = fig.add_subplot(gs[0, 1]) ax_stat = fig.add_subplot(gs[0, 2])因为地图天然是方形的,如果中间的时序图也做成方形,整个一排看起来就很整齐。我建议所有子图的高度一致,宽度按照内容分配,地图约占总宽度三分之一,时序图和统计图共享剩下的空间。
5.4 关于审稿人眼光的一个经验
我审稿时看到过的地图问题,十张里有七八张不是数据算错,而是“图做得不够干净”。所谓干净,我的理解是:元素少而有效、信息没有冗余。很多初学画图的同学恨不得把海岸线做成带阴影的、国界线加粗、经纬网又密又黑、再叠加城市和站点,结果整张图花成一团。
Nature风格恰恰是“少即是多”。陆地浅灰、海洋留白、海岸线细线、网格虚线若隐若现、数据字段用一套克制的色带表达。这种风格并不需要很高的代码水平,需要的是一种克制力。画完图之后,你可以先问自己:这张图里有没有任何一条线是多余的?如果有,删掉它。
6. 我的个人使用体会
这套“几行代码绘制Nature风格北半球投影图”的方案,我用过很多次,从最开始自己也踩过下载数据失败的坑,到后来形成一套固定流程,大约只要五分钟就能从原始数据到一张符合投稿标准的圆盘图。回头来看,Cartopy的学习成本不算高,但关键节点就那么几个:理解坐标系、用好transform、把颜色和字体控制到位、该裁剪时果断裁剪。把这些点逐一拿捏住,再复杂的北半球专题图也不过是在这个骨架上叠加不同的数据层而已。
最后再分享一个小技巧:我一般在正式出图之前,会先用低分辨率、低dpi快速跑一遍流程,确认数据范围、配色、布局都没问题,再调整到高dpi保存最终版。这样既能快速迭代,又不用反复等待大文件写入。这个习惯帮我省下了很多不必要的时间,也让我很少在投稿前的截稿日手忙脚乱。