
本文介绍如何将 choropleth 地图双子图共用的 colorbar 或图例统一置于整个图形底部中央,避免默认绑定在单个子图上,并提供可直接运行的 matplotlib + geopandas 配置方案。
本文介绍如何将 choropleth 地图双子图共用的 colorbar 或图例统一置于整个图形底部中央,避免默认绑定在单个子图上,并提供可直接运行的 matplotlib + geopandas 配置方案。
在使用 geopandas.GeoDataFrame.plot() 绘制双 choropleth 子图时,colorbar=True 参数默认会为每个子图分别生成独立 colorbar(若未禁用),且位置难以精确控制。而用户真正需要的是——一个共享的、水平居中、位于整幅图像底部的 colorbar,这需绕过 plot() 内置 colorbar 机制,改用 fig.colorbar() 手动创建,并关联到共享的归一化对象(matplotlib.colors.Normalize)和 colormap。
以下是完整、可复用的解决方案(基于你原有代码优化):
import matplotlib.pyplot as plt
import matplotlib as mpl
from mpl_toolkits.axes_grid1 import make_axes_locatable
# 假设 a_2020 和 a_dublin 是已加载的 GeoDataFrame,norm 已定义(如:norm = mpl.colors.Normalize(vmin=0, vmax=100))
a_combined_path = 'c:\mypath'
fig, (ax1, ax2) = plt.subplots(1, 2, layout='constrained', figsize=(10, 5)) # 调整高度更合理
# 绘图(关闭内置 colorbar)
a_2020.plot(ax=ax1, column='Party Vote Share', cmap='Greens', edgecolor='black',
linewidth=0.5, norm=norm, legend=False)
a_dublin.plot(ax=ax2, column='Party Vote Share', cmap='Greens', edgecolor='black',
linewidth=0.5, norm=norm, legend=False)
# 关闭坐标轴
ax1.set_axis_off()
ax2.set_axis_off()
ax1.set_title('Republic of Ireland', size=16)
ax2.set_title('Dublin', size=16)
fig.suptitle('Aontú vote share in the 2020 elections
by constituency (Pct of total vote)', size=16)
# ✅ 关键步骤:手动添加全局 colorbar(位于图下方中央)
# 创建一个与 colorbar 宽度匹配的“伪 mappable”对象(无需实际数据)
sm = plt.cm.ScalarMappable(cmap='Greens', norm=norm)
sm.set_array([]) # 必须调用,否则 colorbar 报错
# 添加 colorbar 并精确定位:bottom-center,宽度占图宽 60%,高度固定
cbar = fig.colorbar(sm, ax=[ax1, ax2], orientation='horizontal',
shrink=0.6, aspect=40, pad=0.1)
cbar.set_label('Party Vote Share (%)', fontsize=12)
plt.savefig(a_combined_path, dpi=600, bbox_inches='tight')
plt.show()
✅ 关键要点说明:
- legend=False 在 plot() 中禁用默认图例,避免冲突;
- plt.cm.ScalarMappable 构造一个虚拟可映射对象,使其能被 fig.colorbar() 识别;
- ax=[ax1, ax2] 确保 colorbar 参考两个子图的布局约束;
- orientation='horizontal' + shrink=0.6 + pad=0.1 实现紧凑居中排布;
- bbox_inches='tight' 防止保存时 colorbar 被截断。
⚠️ 注意事项:
- 若使用 geopandas>=0.14,plot(..., legend=True) 的 colorbar 行为已改进,但仍不支持跨子图共享;手动方式兼容性更佳;
- norm 必须在两个 plot() 调用中完全一致,否则 colorbar 刻度与数据不匹配;
- 如需自定义刻度(如显示整数百分比),可在 cbar 后添加:
cbar.set_ticks([0, 25, 50, 75, 100]) cbar.set_ticklabels(['0%', '25%', '50%', '75%', '100%'])
该方法稳定、语义清晰,且完全适配 layout='constrained',无需手动计算 bbox_to_anchor 坐标,是当前 matplotlib 生态下最推荐的 choropleth 多子图 colorbar 统一管理方案。











