Matplotlib多子图设置行标题及全图共用colorbar报错咨询
Matplotlib多子图行标题+全局共用colorbar实现方案
问题描述
需要实现Matplotlib多子图画布的两个核心效果:
- 为每一行子图设置独立的行级标题
- 为全图所有子图配置一个共用的colorbar
实现过程中固定触发报错:
Unable to create a colorbar axes as not all parents share the same figure.
可复现报错的最小代码
import numpy as np import matplotlib.pyplot as plt datarow1 = [np.random.random((10, 10)), np.random.random((10, 10))] datarow2 = [np.random.random((10, 10)), np.random.random((10, 10))] fig = plt.figure(constrained_layout=True) fig.suptitle('Main title', weight='bold', fontsize=20) subfigs = fig.subfigures(2, 1) subfigs[0].suptitle('Title row 1') axesrow1 = subfigs[0].subplots(nrows=1, ncols=2) axesrow1[0].imshow(datarow1[0], vmin=0, vmax=1, cmap='viridis') axesrow1[1].imshow(datarow1[1], vmin=0, vmax=1, cmap='viridis') subfigs[1].suptitle('Title row 2') axesrow2 = subfigs[1].subplots(nrows=1, ncols=2) axesrow2[0].imshow(datarow2[0], vmin=0, vmax=1, cmap='viridis') axesrow2[1].imshow(datarow2[1], vmin=0, vmax=1, cmap='viridis') fig.colorbar(plt.cm.ScalarMappable(cmap='viridis', norm=plt.Normalize(0, 1)), orientation='vertical', ax=fig.get_axes()) plt.show()
预期运行效果参考:
报错根因
调用fig.subfigures()创建嵌套子画布后,fig.get_axes()返回的坐标轴列表包含子画布本身的容器级坐标轴,这些坐标轴分属不同的子父级画布,Matplotlib创建colorbar时校验到传入的坐标轴不共享同一个直接父对象,就会抛出该错误。
修正后可运行代码
只需要手动汇总所有实际绘图的子图坐标轴,替代fig.get_axes()传入colorbar的ax参数即可,原有行标题的实现逻辑不需要改动:
import numpy as np import matplotlib.pyplot as plt datarow1 = [np.random.random((10, 10)), np.random.random((10, 10))] datarow2 = [np.random.random((10, 10)), np.random.random((10, 10))] fig = plt.figure(constrained_layout=True) fig.suptitle('Main title', weight='bold', fontsize=20) subfigs = fig.subfigures(2, 1) subfigs[0].suptitle('Title row 1') axesrow1 = subfigs[0].subplots(nrows=1, ncols=2) axesrow1[0].imshow(datarow1[0], vmin=0, vmax=1, cmap='viridis') axesrow1[1].imshow(datarow1[1], vmin=0, vmax=1, cmap='viridis') subfigs[1].suptitle('Title row 2') axesrow2 = subfigs[1].subplots(nrows=1, ncols=2) axesrow2[0].imshow(datarow2[0], vmin=0, vmax=1, cmap='viridis') axesrow2[1].imshow(datarow2[1], vmin=0, vmax=1, cmap='viridis') # 手动汇总所有实际绘图的子图坐标轴 all_plot_axes = list(axesrow1) + list(axesrow2) fig.colorbar( plt.cm.ScalarMappable(cmap='viridis', norm=plt.Normalize(0, 1)), orientation='vertical', ax=all_plot_axes, fraction=0.02, # 可选:调整colorbar宽度 pad=0.02 # 可选:调整colorbar和子图的间距 ) plt.show()
内容的提问来源于stack exchange,提问作者rvdaele
相关产品推荐
相关产品推荐

