使用Axes.inset_axes添加GeoAxes时出现KeyError:'geo'问题
问题背景
制作气象数据垂直剖面图时,主图用常规matplotlib绘图展示剖面数据,右上角需要嵌入显示剖面位置的cartopy GeoAxes地图。使用Figure.add_axes可成功嵌入GeoAxes,但调用Axes.inset_axes时触发KeyError:'geo'错误,且打印嵌入轴的spines时能看到'geo'关键字及对应Spine对象存在。
环境版本:
- Python 3.10.12
- cartopy 0.22.0
- matplotlib 3.7.2
- jupyter 1.0.0
问题原因
Axes.inset_axes创建嵌入轴时,默认会继承父轴的属性与初始化逻辑,但cartopy的GeoAxes是特殊轴类,内部对spine、投影的处理逻辑和普通matplotlib Axes完全不同。inset_axes的默认流程没有适配这种特殊性,导致初始化过程中触发spine相关的KeyError。
解决方案
方案1:显式指定嵌入轴类型为GeoAxes
直接通过inset_axes的axes_class参数指定使用cartopy的GeoAxes类,并传入投影参数,绕开父轴属性继承带来的冲突。这是最稳妥的方法:
import matplotlib.pyplot as plt import cartopy.crs as ccrs # 创建主图轴(模拟剖面数据绘图) fig, main_ax = plt.subplots(figsize=(10, 6)) main_ax.plot(range(10), range(10)) # 用inset_axes创建GeoAxes,显式指定轴类与投影 inset_ax = main_ax.inset_axes( [0.75, 0.75, 0.2, 0.2], # 位置参数:[左, 下, 宽, 高](归一化坐标) axes_class=ccrs.PlateCarree().__class__, projection=ccrs.PlateCarree() ) inset_ax.coastlines() # 测试添加海岸线 plt.show()
方案2:回退使用Figure.add_axes(已验证可行)
如果上述方案仍有兼容性问题,可以继续使用Figure.add_axes创建嵌入的GeoAxes,通过计算主图轴的坐标来定位嵌入图:
import matplotlib.pyplot as plt import cartopy.crs as ccrs fig, main_ax = plt.subplots(figsize=(10, 6)) main_ax.plot(range(10), range(10)) # 计算嵌入图的归一化坐标(基于主图轴位置) main_bbox = main_ax.get_position() inset_bbox = [ main_bbox.x0 + main_bbox.width * 0.7, main_bbox.y0 + main_bbox.height * 0.7, 0.2, 0.2 ] # 创建GeoAxes嵌入图 inset_ax = fig.add_axes(inset_bbox, projection=ccrs.PlateCarree()) inset_ax.coastlines() plt.show()
方案3:替换已有inset轴的类(不推荐)
若需保留父轴部分属性,可先创建普通inset轴,再手动替换为GeoAxes类并初始化投影,但这种方法可能引发其他未知兼容性问题,仅作参考:
inset_ax = main_ax.inset_axes([0.75, 0.75, 0.2, 0.2]) # 替换轴类并初始化cartopy投影 inset_ax.__class__ = ccrs.PlateCarree().__class__ inset_ax._init_projection(ccrs.PlateCarree()) inset_ax.coastlines()
关键提示
cartopy的GeoAxes并非标准matplotlib Axes的直接子类,其内部对spine、投影的处理逻辑独立于普通轴。inset_axes的默认初始化流程没有适配这种特殊轴类,因此显式指定axes_class是最可靠的解决方式。
内容的提问来源于stack exchange,提问作者Benjamin Ascher

