You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GeoPandas多子图:共享图例、坐标轴及控制图尺寸的实现方法

解决GeoPandas多子图共享坐标轴、图例及控制画布大小的问题

嘿,我来帮你搞定这个问题!你之前踩的坑都是因为没找对sharex/sharey的正确打开方式,还有多子图图例重复的问题,咱们一步步来修正:

先说说你之前的错误原因

  • plt.figure()根本没有sharex/sharey参数,这些是批量创建子图的plt.subplots()的专属参数,所以第一个调用会报错。
  • GeoPandas的plot()方法不接受sharex/sharey,这些是Matplotlib坐标轴(Axes)的属性,不能直接传给绘图函数。
  • plt.subplot()的sharex/sharey需要指定要共享的坐标轴对象(比如sharex=axs[0,0]),而不是直接传True,不然会触发弱引用的错误。

正确的实现代码

下面是调整后的完整代码,我标注了关键修改点:

import pandas as pd
import geopandas as gpd
import matplotlib.pyplot as plt

# 加载数据
world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
months = pd.DataFrame(
    ["January", "February", "March", "April", "May", "June", 
     "July", "August", "September", "October", "November", "December"], 
    columns=['months']
)

# 关键1:用plt.subplots一次性创建所有子图,设置共享轴和画布大小
fig, axs = plt.subplots(
    nrows=4, ncols=3, 
    sharex=True, sharey=True,  # 这里设置共享x/y轴
    figsize=(15, 12)  # 控制整个画布的大小,按需调整
)

# 把二维的axs数组展平成一维,方便循环
axs_flat = axs.flatten()

# 循环绘制每个子图
for idx, (month, ax) in enumerate(zip(months['months'], axs_flat)):
    # 绘制地图,注意只在最后一个子图添加图例(避免重复)
    plot = world.plot(
        column='pop_est', 
        ax=ax, 
        legend=(idx == 11),  # 最后一个子图才显示图例
        legend_kwds={'shrink': 0.6}  # 调整图例大小,避免占空间
    )
    ax.set_title(month, fontsize=10)
    ax.set_aspect('equal', adjustable='datalim')

# 设置整体标题
plt.suptitle('全球人口估算(按月份展示)', fontsize=14, y=1.02)
# 调整子图间距,避免标题和子图重叠
plt.tight_layout()

plt.show()

额外优化:更美观的共享图例

如果觉得最后一个子图的图例挤,也可以把图例单独放到画布右侧,这样所有子图共享一个全局图例:

import pandas as pd
import geopandas as gpd
import matplotlib.pyplot as plt

world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
months = pd.DataFrame(
    ["January", "February", "March", "April", "May", "June", 
     "July", "August", "September", "October", "November", "December"], 
    columns=['months']
)

fig, axs = plt.subplots(4, 3, sharex=True, sharey=True, figsize=(15, 12))
axs_flat = axs.flatten()

# 先绘制第一个子图,获取颜色映射对象
first_plot = world.plot(column='pop_est', ax=axs_flat[0])
axs_flat[0].set_title(months['months'][0], fontsize=10)
axs_flat[0].set_aspect('equal', adjustable='datalim')

# 绘制剩下的子图,不添加图例
for idx in range(1, 12):
    world.plot(column='pop_est', ax=axs_flat[idx], legend=False)
    axs_flat[idx].set_title(months['months'][idx], fontsize=10)
    axs_flat[idx].set_aspect('equal', adjustable='datalim')

# 创建全局共享图例
fig.colorbar(first_plot.collections[0], ax=axs, orientation='vertical', shrink=0.8, label='人口估算')

plt.suptitle('全球人口估算(按月份展示)', fontsize=14, y=1.02)
plt.tight_layout()
plt.show()

这样做的好处是图例统一在右侧,不会占用子图的空间,视觉上更整洁。

内容的提问来源于stack exchange,提问作者Stücke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 20:09:05