Matplotlib绘制3变量6子图代码报错排查与修改方案咨询
问题说明
现有变量列表 var = [var1, var2, var3],每个元素是包含2个元素的列表:
- var1 形状为 (129,135)
- var2、var3 形状为 (201,321)
需要用Matplotlib绘制3行2列共6个子图,且每行对应一个独立色条。但运行提供的代码时出现三个报错:
AttributeError: 'AxesSubplot' object has no attribute 'add_feature'AttributeError: 'AxesSubplot' object has no attribute 'gridlines'AttributeError: 'AxesSubplot' object has no attribute 'set_extent'
原代码如下:
fs=12 # font size fig, axs = plt.subplots(3, 2, figsize=(6,8), dpi=300) titl='H_L ' fig.suptitle(titl,fontsize=fs, weight='normal') fig.subplots_adjust(hspace= 0.4, wspace=0.5) # gap between the subplots for h in range (3) : for i in range(2) : ax = axs[h, i] sub_titl = ['H','L' ] ax.set_title(sub_titl[i], fontsize=fs, weight= 'bold' ) ax.background_patch.add_feature(feature.NaturalEarthFeature(category='cultural', name='admin_1_states_provinces_lines', scale='50m', facecolor='none')) gl = ax.gridlines(crs=ccrs.PlateCarree(), linewidth=1, color='grey', alpha=0.3, linestyle='-', draw_labels=True) gl.top_labels = False gl.right_labels = False gl.xformatter = LONGITUDE_FORMATTER gl.yformatter = LATITUDE_FORMATTER gl.xlabel_style = {'size': fs} gl.ylabel_style = {'size': fs} clist = ['#7f0000','#a50f15','#cb181d','#ef3b2c','#fb6a4a','#fc9272','#fcbba1','#fee0d2','#92c5de','#4393c3','#2166ac','#053061'] cmap = mcolors.ListedColormap(clist) # cticks = np.arange(-20,45,5) # norm = mcolors.BoundaryNorm(cticks, cmap.N, clip=True) bbox = [65,100,6.5,40] X, Y = np.meshgrid(f1.LONGITUDE, f1.LATITUDE) # for rf_anom if h > 0: bbox = [40,120,-10,40] ax.set_extent(bbox[h],crs=ccrs.PlateCarree()) X, Y = np.meshgrid(f2.lon, f2.lat) iax=ax.pcolormesh(X,Y,var[h][i], cmap=cmap # cmap = cmap.reversed(), # norm = norm, ) ax.coastlines() cticks1 = np.arange(-20,50,10) cbar = fig.colorbar(iax,ax=ax, # 3 different colorbar location='right', pad=0.05, drawedges=True, shrink=0.8, fraction=0.04, aspect=18, orientation= 'vertical', extend='both', # ticks=cticks1 ) # colorbar settings cbar.ax.tick_params(labelsize=fs)
报错原因&代码问题
这些报错的根源很明确:你调用的add_feature、gridlines、set_extent都是**Cartopy地理坐标轴(GeoAxes)**的专属方法,但默认plt.subplots()创建的是普通Matplotlib AxesSubplot对象,根本不支持这些地理绘图功能。
除此之外,原代码还有不少逻辑漏洞:
- 色条绑定逻辑混乱:原代码在每行循环结束后绑色条,但
iax只在h>0时赋值,且未关联整行子图 bbox[h]索引越界:bbox是长度为4的列表,h取1、2时直接索引会报错- 第一行子图(h=0)未绘制任何填色内容
- 缩进错误:色条代码的缩进位置不对,导致执行逻辑完全不符合预期
修改后的完整代码
import matplotlib.pyplot as plt import numpy as np import matplotlib.colors as mcolors import cartopy.crs as ccrs from cartopy.feature import NaturalEarthFeature from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER # 假设f1、f2、var已提前定义好 fs=12 # 字体大小 # 创建带Cartopy投影的地理子图,这是解决报错的核心 fig, axs = plt.subplots(3, 2, figsize=(6,8), dpi=300, subplot_kw={'projection': ccrs.PlateCarree()}) titl='H_L ' fig.suptitle(titl, fontsize=fs, weight='normal') fig.subplots_adjust(hspace=0.4, wspace=0.5) # 子图间距设置 # 定义自定义色标 clist = ['#7f0000','#a50f15','#cb181d','#ef3b2c','#fb6a4a','#fc9272','#fcbba1','#fee0d2','#92c5de','#4393c3','#2166ac','#053061'] cmap = mcolors.ListedColormap(clist) cticks1 = np.arange(-20,50,10) for h in range(3): row_images = [] # 存储当前行的绘图对象,用于后续创建统一色条 for i in range(2): ax = axs[h, i] sub_titl = ['H','L'] ax.set_title(sub_titl[i], fontsize=fs, weight='bold') # 添加省级行政边界 state_lines = NaturalEarthFeature(category='cultural', name='admin_1_states_provinces_lines', scale='50m', facecolor='none', edgecolor='black') ax.add_feature(state_lines) # 添加网格线与经纬度标签 gl = ax.gridlines(crs=ccrs.PlateCarree(), linewidth=1, color='grey', alpha=0.3, linestyle='-', draw_labels=True) gl.top_labels = False gl.right_labels = False gl.xformatter = LONGITUDE_FORMATTER gl.yformatter = LATITUDE_FORMATTER gl.xlabel_style = {'size': fs} gl.ylabel_style = {'size': fs} # 根据行设置绘图范围和数据网格 if h == 0: bbox = [65,100,6.5,40] X, Y = np.meshgrid(f1.LONGITUDE, f1.LATITUDE) plot_data = var[h][i] else: bbox = [40,120,-10,40] X, Y = np.meshgrid(f2.lon, f2.lat) plot_data = var[h][i] ax.set_extent(bbox, crs=ccrs.PlateCarree()) # 绘制填色图,指定坐标转换 im = ax.pcolormesh(X, Y, plot_data, cmap=cmap, transform=ccrs.PlateCarree()) row_images.append(im) # 添加海岸线 ax.coastlines() # 为当前行创建统一色条,绑定该行的两个子图 cbar = fig.colorbar(row_images[0], ax=axs[h, :], location='right', pad=0.05, drawedges=True, shrink=0.8, fraction=0.04, aspect=18, orientation='vertical', extend='both', ticks=cticks1) cbar.ax.tick_params(labelsize=fs) plt.show()
关键修改点
- 地理坐标轴创建:通过
subplot_kw={'projection': ccrs.PlateCarree()}指定Cartopy投影,让Axes对象支持地理绘图方法,直接解决三个AttributeError - 行级色条绑定:每行子图绘制完成后,将色条绑定到整行(
ax=axs[h, :]),实现每行一个独立色条的需求 - 逻辑补全:补充了h=0时的绘图代码,确保所有子图都有内容
- 索引修复:去掉了错误的
bbox[h]索引,直接使用完整的bbox列表设置范围 - 缩进修正:调整色条代码的缩进,使其在每行子图绘制完成后执行,逻辑更清晰
内容的提问来源于stack exchange,提问作者Seraphina
相关产品推荐
相关产品推荐

