如何为每行数据绘制子图?GeoDataFrames子图异常及标题添加需求
问题:GeoDataFrames绘制7×6子图异常及整体标题添加
问题说明
- 使用GeoDataFrames绘制7行6列子图时,无法让所有数据正常显示
- 需要为整个子图集合添加标题「Mean ET Data for SD-6 Area」
- 所有待绘制的GeoDataFrames结构一致
现有代码
# what I want to label the y axis for each row ylab = ['mean_ensemble', 'mean_disalexi', 'mean_eemetric', 'mean_geesebal', 'mean_ptjpl', 'mean_ssebop', 'mean_sims'] # the years I want to plot and what the name of each column in the geodataframes are years = ['2016', '2017', '2018', '2019', '2020', '2021'] # the 7 geodataframes graph = [mean_ensemble, mean_disalexi, mean_eemetric, mean_geesebal, mean_ptjpl, mean_ssebop, mean_sims] f, ax = plt.subplots(nrows = 7, ncols = 6, figsize = (12, 12)) ax = ax.flatten() i=0 for y, col in enumerate(years): graph[i].plot(column=col, ax=ax[y], legend=True, cmap='Blues') ax[y].axis('off') plt.title(str(y)) i+=1 plt.show()
问题分析
现有代码核心逻辑错误:
- 仅遍历6个年份,只绘制了第一行的6个子图,剩余36个轴完全未使用
- 仅调用了第一个GeoDataFrame,其余6个未参与绘制
plt.title()会覆盖之前的子图标题,无法为每个子图设置正确标识
修正方案
以下是调整后的代码,解决数据显示问题并添加整体标题:
# 行标签 ylab = ['mean_ensemble', 'mean_disalexi', 'mean_eemetric', 'mean_geesebal', 'mean_ptjpl', 'mean_ssebop', 'mean_sims'] # 年份列名 years = ['2016', '2017', '2018', '2019', '2020', '2021'] # GeoDataFrames列表 graph = [mean_ensemble, mean_disalexi, mean_eemetric, mean_geesebal, mean_ptjpl, mean_ssebop, mean_sims] # 创建7行6列子图,放大尺寸适配多子图布局 f, ax = plt.subplots(nrows=7, ncols=6, figsize=(18, 21)) # 添加整体标题,调整y参数避免和子图标题重叠 f.suptitle('Mean ET Data for SD-6 Area', fontsize=16, y=0.98) # 嵌套循环遍历所有行和列 for row_idx, (gdf, y_label) in enumerate(zip(graph, ylab)): for col_idx, year in enumerate(years): current_ax = ax[row_idx, col_idx] # 绘制地理数据,先不添加图例避免重复 im = gdf.plot(column=year, ax=current_ax, cmap='Blues', legend=False) current_ax.axis('off') # 仅给第一列子图添加行标签,优化布局 if col_idx == 0: current_ax.set_ylabel(y_label, fontsize=12, rotation=0, labelpad=30) # 仅给第一行子图添加年份标题 if row_idx == 0: current_ax.set_title(year, fontsize=12) # 统一添加共享图例,避免每个子图都显示图例造成拥挤 from mpl_toolkits.axes_grid1 import make_axes_locatable divider = make_axes_locatable(ax[-1, -1]) cax = divider.append_axes("right", size="5%", pad=0.1) f.colorbar(im, cax=cax) # 调整子图间距,给整体标题留出空间 plt.tight_layout(rect=[0, 0, 1, 0.96]) plt.show()
关键修正点
- 保留二维轴数组:不提前flatten,通过
ax[row_idx, col_idx]精准定位每个子图,确保覆盖所有42个绘图区域 - 嵌套循环遍历:外层遍历每个GeoDataFrame(对应行),内层遍历每个年份(对应列),保证所有数据都被绘制
- 整体标题添加:使用
f.suptitle()给整个图集合添加标题,通过y参数调整位置避免遮挡 - 优化布局细节:仅在第一列添加行标签、第一行添加年份标题,统一共享图例,避免布局混乱
- 调整尺寸与间距:放大figsize并使用
tight_layout(rect),适配多子图并留出整体标题空间
内容的提问来源于stack exchange,提问作者Ashley Grinstead
相关产品推荐
相关产品推荐

