如何将地图图例放置在地图外部?Geopandas+BASemap图例问题
问题:Basemap底图上Shapefile图例位置设置错误及解决方法
场景说明
在Basemap底图上加载shapefile,基于Ecoregion列对多边形分类着色,希望将图例放置在地图外部侧边,但遇到两个问题:
- 调用
ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left')时出现错误:
WARNING:matplotlib.legend:No handles with labels found to put in legend.
- 在
data.plot()中添加legend=True后,图例默认显示在地图上方,不符合需求。
错误原因解释
- 关于handle的定义:这里的handle是matplotlib中代表可视化元素(如多边形、线条)的对象,用于关联图例标签。当用
geopandas的plot(column=...)按列分类着色时,默认不会自动为每个Ecoregion类别生成带对应标签的handle,因此ax.legend()找不到可生成图例的元素,触发报错。 legend=True的默认行为:geopandas的plot方法中设置legend=True时,会自动生成图例,但默认将图例放置在绘图区域内部,因此会覆盖在地图上方。
解决方法及修正代码
要解决这个问题,需要统一绘图轴、手动生成图例的handle和标签,并指定图例位置到地图外部:
完整修正代码
# 安装依赖(仅首次运行需要) # pip install geopandas contextily basemap matplotlib numpy import geopandas as gpd import contextily as ctx import matplotlib.pyplot as plt import numpy as np from mpl_toolkits.basemap import Basemap # 加载shapefile数据 data = gpd.read_file("icemap.shp") plt.rcParams.update({'font.size': 14}) # 创建绘图轴,后续Basemap使用同一轴 fig, ax = plt.subplots(figsize=(12, 10)) # 按Ecoregion列着色多边形,获取颜色映射 cmap = plt.get_cmap("tab10") # 获取唯一的Ecoregion类别及对应颜色 unique_regions = data["Ecoregion"].unique() color_list = [cmap(i) for i in range(len(unique_regions))] # 绘制shapefile,为每个类别分配颜色并添加标签 for region, color in zip(unique_regions, color_list): data[data["Ecoregion"] == region].plot(ax=ax, color=color, label=region) # 初始化Basemap并绑定到同一轴 map = Basemap( llcrnrlon=-50, llcrnrlat=30, urcrnrlon=70.0, urcrnrlat=85.0, resolution="i", lat_0=39.5, lon_0=1, ax=ax ) # 绘制Basemap基础元素 map.fillcontinents(color="lightgreen") map.drawcoastlines() map.drawparallels(np.arange(10,90,20), labels=[1,1,1,1]) map.drawmeridians(np.arange(-180,180,30), labels=[1,1,0,1]) # 生成并放置图例到地图侧边 ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0) plt.title("Map", fontsize=16) # 调整布局避免图例被裁剪 plt.tight_layout() plt.show()
关键修改点
- 统一绘图轴:创建
fig, ax后,让Basemap和geopandas的plot都使用这个轴,避免图层分离和元素错位问题。 - 手动生成带标签的handle:遍历每个
Ecoregion类别,单独绘制并指定label,让ax.legend()能找到对应的可视化元素和标签。 - 调整图例位置:通过
bbox_to_anchor=(1.05, 1)将图例放置在轴的右侧外部,plt.tight_layout()确保图例不会被画布边缘裁剪。
内容的提问来源于stack exchange,提问作者Kee C
相关产品推荐
相关产品推荐

