使用plt.subplots实现12个Cartopy地图3行4列排布时的TypeError报错问题
报错核心原因
- 循环解包逻辑错误:原代码中
for i in zip(range(12),ax.ravel()):会将i赋值为包含整数索引和子图对象的元组,后续直接用climatology[i]索引xarray数组时,传入的元组不满足整数索引要求,直接触发类型错误。 - 子图初始化逻辑错误:原代码通过
plt.subplots生成的是普通直角坐标轴,循环中又通过plt.axes()重新创建无位置约束的投影轴,完全脱离3行4列的网格布局,会导致轴位置错乱、图层互相覆盖。 - 冗余参数与变量错位:
ax.contourf()是轴对象的内置方法,不需要额外传入ax=ax参数;且循环内反复重写全局变量ax,会彻底打乱原有子图的引用关系。 - 绘图流程错位:将
plt.show()放在循环内部,会每遍历一次子图就弹出一次画布,无法生成完整的网格图。
修正步骤
- 初始化子图时直接为所有子图指定Cartopy投影,避免后续重复创建轴
- 遍历网格时正确解包数据索引与子图对象,避免将元组作为数组索引
- 移除循环内多余的
plt.axes()调用、冗余的方法参数 - 将画布展示逻辑移到所有子图绘制完成后执行
可运行修正代码
import matplotlib.pyplot as plt import cartopy.crs as ccrs import cartopy.feature as cfeature import numpy as np # 3行4列生成带投影的子图,直接指定Cartopy投影参数 fig, axs = plt.subplots( nrows=3, ncols=4, figsize=(15, 12), subplot_kw={'projection': ccrs.PlateCarree()} ) # 正确解包整数索引与对应子图对象 for idx, ax_cur in zip(range(12), axs.ravel()): # 配置当前子图的地图范围 ax_cur.set_extent([-90, 10, 5, 85], crs=ccrs.PlateCarree()) # 绘制填色等值线,移除冗余的ax参数 plot_handle = ax_cur.contourf( longitude, latitude, climatology[idx], np.arange(28, 39, .3), cmap='jet', extend='both' ) ax_cur.coastlines() # 取消注释可添加陆地边界要素 # ax_cur.add_feature(cfeature.LAND, zorder=100, edgecolor='k') # 绘制带标签的网格线 ax_cur.gridlines(draw_labels=True) # 为当前子图绑定专属色标 cbar = fig.colorbar(plot_handle, ax=ax_cur, fraction=.046, pad=0.04) cbar.set_label('psu', labelpad=15, y=.5, rotation=90) # 添加轴标签 ax_cur.text( .5, -.12, 'Longitude', va='bottom', ha='center', rotation='horizontal', rotation_mode='anchor', transform=ax_cur.transAxes ) ax_cur.text( -.1, .5, 'Latitude', va='bottom', ha='center', rotation='vertical', rotation_mode='anchor', transform=ax_cur.transAxes ) # 统一调整布局避免标签重叠,完成所有绘制后再展示 plt.tight_layout() plt.show()
关键调整说明
- 变量命名隔离:用
axs保存所有子图的数组对象,循环内用ax_cur指代当前操作的子图,避免和全局变量重名造成引用混乱 - 色标绑定逻辑:通过
fig.colorbar(..., ax=ax_cur)显式将色标和对应子图绑定,避免色标位置错位 - 尺寸适配:原figsize=(15,5)适配3行布局时高度不足,调整为15,12保证每个子图比例正常
- 布局优化:加入
tight_layout()自动调整子图间距,防止3行布局下的轴标签、色标互相遮挡
内容的提问来源于stack exchange,提问作者wabash
相关产品推荐
相关产品推荐

