使用inset_axes嵌入Cartopy南极投影地图报错,求解决方案
解决Cartopy嵌入子图投影报错及剖面位置地图嵌入问题
问题描述
已生成多个特定经度的海洋剖面图,希望在每个剖面图子图中嵌入显示该剖面位置的地图,添加嵌入地图代码后出现以下问题:
- 报错
NameError: name 'SouthPolarStereo' is not defined - 尝试其他投影时出现
KeyError 'geo'
原代码片段:
import matplotlib.pyplot as plt import matplotlib.path as mpath import numpy as np import pandas as pd import xarray as xr import cartopy import cartopy.crs as ccrs num_plots = len(range(0, 360, 20)) cols = 2 # Number of columns in the subplot grid rows = (num_plots + cols - 1) // cols # Calculate the number of rows fig, axs = plt.subplots(rows, cols, figsize=(20, 40)) for idx, ax, in zip(range(0, 360, 20), axs.flat): im = mydataselection.plot(cmap='plasma', vmin=-2, vmax=8, ax=ax) ax.invert_yaxis() ax.set_title(f"titlestring") ax.set_xticks(xtickvalues) ax.set_xticklabels(np.round(xticklabelvalues,1)) ax.set_xlabel('Longitude [°N]') axins = ax.inset_axes([0.1, 0.1, 0.2, 0.3], projection=SouthPolarStereo()) axins.set_extent([-180, 180, -90, -50], ccrs.PlateCarree()) axins.add_feature(cartopy.feature.LAND, edgecolor='black', facecolor='gray') axins.add_feature(cartopy.feature.OCEAN) axins.gridlines() # Make circular inset map circle = PathPatch(Path.circle((0.5, 0.5), radius=0.5), transform=axins.transAxes, facecolor='none', edgecolor='black') axins.add_patch(circle) # Hide any remaining empty subplots for ax in axs.flat[num_plots:]: ax.axis('off') plt.tight_layout() plt.subplots_adjust(top=0.9) plt.show()
错误原因分析
- NameError:
SouthPolarStereo是cartopy.crs模块下的类,代码中直接调用SouthPolarStereo()未加导入的模块前缀ccrs.,导致Python找不到该类。 - KeyError 'geo':一是路径对象引用错误,导入的是
matplotlib.path as mpath,但代码中直接用Path和PathPatch未加mpath.前缀;二是matplotlib的inset_axes默认不自动兼容cartopy投影,需确保参数传递正确。
修正方案及完整代码
关键修正点:
- 投影类调用改为
ccrs.SouthPolarStereo() - 路径对象改为
mpath.Path和mpath.PathPatch - 在嵌入地图中添加当前剖面的经度线,明确标注位置
- 调整圆形遮罩的创建方式,适配cartopy极地投影
修正后的完整代码:
import matplotlib.pyplot as plt import matplotlib.path as mpath import numpy as np import pandas as pd import xarray as xr import cartopy import cartopy.crs as ccrs num_plots = len(range(0, 360, 20)) cols = 2 # Number of columns in the subplot grid rows = (num_plots + cols - 1) // cols # Calculate the number of rows fig, axs = plt.subplots(rows, cols, figsize=(20, 40)) for idx, ax in zip(range(0, 360, 20), axs.flat): # 绘制海洋剖面图(保留原有逻辑) im = mydataselection.plot(cmap='plasma', vmin=-2, vmax=8, ax=ax) ax.invert_yaxis() ax.set_title(f"Longitude: {idx}°E") ax.set_xticks(xtickvalues) ax.set_xticklabels(np.round(xticklabelvalues, 1)) ax.set_xlabel('Latitude [°N]') # 修正原代码标注错误,沿经度切的剖面横轴应为纬度 # 创建嵌入地图的子轴,使用正确的cartopy投影 axins = ax.inset_axes([0.1, 0.1, 0.2, 0.3], projection=ccrs.SouthPolarStereo()) axins.set_extent([-180, 180, -90, -50], ccrs.PlateCarree()) # 添加地图要素 axins.add_feature(cartopy.feature.LAND, edgecolor='black', facecolor='gray') axins.add_feature(cartopy.feature.OCEAN) axins.gridlines(draw_labels=False) # 绘制当前剖面的经度线(红色线条标注位置) axins.plot([idx, idx], [-90, -50], color='red', linewidth=2, transform=ccrs.PlateCarree()) # 创建圆形遮罩,适配极地投影边界 theta = np.linspace(0, 2*np.pi, 100) center, radius = [0.5, 0.5], 0.5 verts = np.vstack([np.sin(theta), np.cos(theta)]).T circle_path = mpath.Path(verts * radius + center) axins.set_boundary(circle_path, transform=axins.transAxes) # 隐藏空的子图 for ax in axs.flat[num_plots:]: ax.axis('off') plt.tight_layout() plt.subplots_adjust(top=0.9) plt.show()
额外说明
- 红色线条明确标记当前剖面的经度位置,方便主图与嵌入地图的对应
- 圆形遮罩改用
mpath.Path生成,适配cartopy极地投影的边界显示 - 修正了原代码中横轴标注的错误,符合海洋经度剖面的常规逻辑
内容的提问来源于stack exchange,提问作者Jan
相关产品推荐
相关产品推荐

