如何为Matplotlib子图网格添加全局X/Y轴标签?
解决Matplotlib子图网格全局X/Y轴标签不显示的问题
问题描述
我尝试在一幅子图网格中绘制多组实验的汇总结果以对比数据,已通过subfigures成功创建子图网格,并添加了行标题及每个子图的标题,但无法显示全局X/Y轴标签。尝试过直接用plt.xlabel()、获取当前轴fig.gca()设置标签都无效,虽然可以给每个子图单独加标签,但希望实现全局统一的轴标签。
原代码
import pandas as pd import numpy as np import matplotlib.pyplot as plt plt.rcParams["figure.figsize"] = (20,20) # 调整图大小以适配内容 fig = plt.figure(constrained_layout=True) fig.suptitle(f'The big title of the set') # 尝试1:直接设置全局标签 plt.xlabel('The X-Label for all graphs') plt.ylabel('The Y-Label for all graphs') # 修正原代码笔误:ply→plt # 尝试2:通过当前轴设置标签 axes = fig.gca() axes.set_xlabel('The X-Label for all graphs', loc='left') axes.set_ylabel('The Y-Label for all graphs', visible=True) Rows = ['four', 'parts', 'of', 'data'] # 补充示例数据 Columns = ['four', 'parts', 'of', 'values', 'per', 'row'] # 补充示例数据 subfigs = fig.subfigures(nrows=len(Rows), ncols=1) for row, subfig in zip(Rows, subfigs): subfig.suptitle(f'Title of row {row}') subsubfigs = subfig.subplots(nrows=1, ncols=len(Columns)) for column, subsubfig in zip(Columns, subsubfigs): # 替换为实际业务数据 row_data = np.arange(10) column_data = np.random.randn(10) subsubfig.plot(row_data, column_data) subsubfig.set_title(f'Title of single graph {row}:{column}') plt.show()
问题原因
你用fig.subfigures()创建的是子Figure对象,而非子Axes绘图轴。主Figure本身没有用于绘图的Axes,plt.gca()获取到的是一个默认创建的隐藏轴,它不会显示在子图网格中,所以设置的标签自然看不到。此外,plt.xlabel()本质也是给当前Axes设置标签,同样不作用于全局。
解决方案
方法1:用fig.text()手动添加全局标签
直接在主Figure的指定位置添加文本作为全局标签,通过归一化坐标(范围0-1)定位:
import pandas as pd import numpy as np import matplotlib.pyplot as plt plt.rcParams["figure.figsize"] = (20,20) fig = plt.figure(constrained_layout=True) fig.suptitle(f'The big title of the set') Rows = ['four', 'parts', 'of', 'data'] Columns = ['four', 'parts', 'of', 'values', 'per', 'row'] subfigs = fig.subfigures(nrows=len(Rows), ncols=1) for row, subfig in zip(Rows, subfigs): subfig.suptitle(f'Title of row {row}') subsubfigs = subfig.subplots(nrows=1, ncols=len(Columns)) for column, subsubfig in zip(Columns, subsubfigs): row_data = np.arange(10) column_data = np.random.randn(10) subsubfig.plot(row_data, column_data) subsubfig.set_title(f'Title of single graph {row}:{column}') # 添加全局X/Y轴标签,坐标可根据布局微调 fig.text(0.5, 0.02, 'The X-Label for all graphs', ha='center', fontsize=12) fig.text(0.02, 0.5, 'The Y-Label for all graphs', va='center', rotation='vertical', fontsize=12) plt.show()
ha='center':水平居中对齐va='center':垂直居中对齐
方法2:共享子图轴标签并统一显示
如果所有子图的X/Y轴含义一致,可以让每行/列的子图共享轴,然后只给边缘子图设置标签,模拟全局标签效果:
import pandas as pd import numpy as np import matplotlib.pyplot as plt plt.rcParams["figure.figsize"] = (20,20) fig = plt.figure(constrained_layout=True) fig.suptitle(f'The big title of the set') Rows = ['four', 'parts', 'of', 'data'] Columns = ['four', 'parts', 'of', 'values', 'per', 'row'] subfigs = fig.subfigures(nrows=len(Rows), ncols=1) for row_idx, (row, subfig) in enumerate(zip(Rows, subfigs)): subfig.suptitle(f'Title of row {row}') # 创建共享Y轴的子图,避免重复显示Y刻度 subsubfigs = subfig.subplots(nrows=1, ncols=len(Columns), sharey=True) for col_idx, (column, subsubfig) in enumerate(zip(Columns, subsubfigs)): row_data = np.arange(10) column_data = np.random.randn(10) subsubfig.plot(row_data, column_data) subsubfig.set_title(f'Title of single graph {row}:{column}') # 只给每行第一个子图加Y标签 if col_idx == 0: subsubfig.set_ylabel('The Y-Label for all graphs') # 只给最后一行的子图加X标签 if row_idx == len(Rows)-1: subsubfig.set_xlabel('The X-Label for all graphs') plt.show()
这种方式更贴合Matplotlib的布局逻辑,无需手动调整坐标。
内容的提问来源于stack exchange,提问作者Kerek
相关产品推荐
相关产品推荐

