我有以下情节:
fig,ax = plt.subplots(5,2,sharex=True,sharey=True,figsize=fig_size)
现在我想给这个图绘制常见的x轴标签和y轴标签。使用" common",我的意思是在整个子图网格下面应该有一个大的x轴标签,在右边有一个大的y轴标签。我在plt.subplots
的文档中找不到任何关于此内容的信息,我的Google搜索建议我需要创建一个大的plt.subplot(111)
- 但我怎么把我的5 * 2使用plt.subplots
?
答案 0 :(得分:155)
这看起来像你真正想要的。它将this answer的相同方法应用于您的具体案例:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(nrows=3, ncols=3, sharex=True, sharey=True, figsize=(6, 6))
fig.text(0.5, 0.04, 'common X', ha='center')
fig.text(0.04, 0.5, 'common Y', va='center', rotation='vertical')
答案 1 :(得分:33)
没有sharex=True, sharey=True
你得到:
有了它你应该更好:
fig, axes2d = plt.subplots(nrows=3, ncols=3,
sharex=True, sharey=True,
figsize=(6,6))
for i, row in enumerate(axes2d):
for j, cell in enumerate(row):
cell.imshow(np.random.rand(32,32))
plt.tight_layout()
但是如果你想添加额外的标签,你应该只将它们添加到边缘图中:
fig, axes2d = plt.subplots(nrows=3, ncols=3,
sharex=True, sharey=True,
figsize=(6,6))
for i, row in enumerate(axes2d):
for j, cell in enumerate(row):
cell.imshow(np.random.rand(32,32))
if i == len(axes2d) - 1:
cell.set_xlabel("noise column: {0:d}".format(j + 1))
if j == 0:
cell.set_ylabel("noise row: {0:d}".format(i + 1))
plt.tight_layout()
为每个情节添加标签会破坏它(可能有一种方法可以自动检测重复的标签,但我不知道一个)。
答案 2 :(得分:18)
由于我认为它足够相关且优雅(无需指定坐标来放置文本),因此我进行了复制(稍作改动)an answer to another related question。
import matplotlib.pyplot as plt
fig, axes = plt.subplots(5, 2, sharex=True, sharey=True, figsize=(6,15))
# add a big axis, hide frame
fig.add_subplot(111, frameon=False)
# hide tick and tick label of the big axis
plt.tick_params(labelcolor='none', top=False, bottom=False, left=False, right=False)
plt.xlabel("common X")
plt.ylabel("common Y")
结果如下(使用matplotlib版本2.2.0):
答案 3 :(得分:14)
自命令:
fig,ax = plt.subplots(5,2,sharex=True,sharey=True,figsize=fig_size)
你使用过返回一个由图形和轴实例列表组成的元组,这已经足够做(比如我已将fig,ax
改为fig,axes
):
fig,axes = plt.subplots(5,2,sharex=True,sharey=True,figsize=fig_size)
for ax in axes:
ax.set_xlabel('Common x-label')
ax.set_ylabel('Common y-label')
如果您想要更改特定子图上的某些详细信息,可以通过axes[i]
访问它,其中i
遍历您的子图。
包含
可能也非常有帮助fig.tight_layout()
在文件的末尾,在plt.show()
之前,以避免重叠标签。
答案 4 :(得分:2)
我在绘制图形网格时遇到了类似的问题。图表由两部分组成(顶部和底部)。 y标签应该以两个部分为中心。
我不想使用依赖于知道外图中位置的解决方案(如fig.text()),因此我操纵了set_ylabel()函数的y位置。它通常是0.5,它被添加到的图的中间。由于我的代码中的部分(hspace)之间的填充为零,我可以计算相对于上部的两个部分的中间部分。
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
# Create outer and inner grid
outerGrid = gridspec.GridSpec(2, 3, width_ratios=[1,1,1], height_ratios=[1,1])
somePlot = gridspec.GridSpecFromSubplotSpec(2, 1,
subplot_spec=outerGrid[3], height_ratios=[1,3], hspace = 0)
# Add two partial plots
partA = plt.subplot(somePlot[0])
partB = plt.subplot(somePlot[1])
# No x-ticks for the upper plot
plt.setp(partA.get_xticklabels(), visible=False)
# The center is (height(top)-height(bottom))/(2*height(top))
# Simplified to 0.5 - height(bottom)/(2*height(top))
mid = 0.5-somePlot.get_height_ratios()[1]/(2.*somePlot.get_height_ratios()[0])
# Place the y-label
partA.set_ylabel('shared label', y = mid)
plt.show()
缺点:
图表的水平距离基于顶部,底部的标记可能会延伸到标签中。
公式不会考虑部件之间的空间。
当顶部的高度为0时抛出异常。
可能有一个通用的解决方案,需要考虑数字之间的填充。
答案 5 :(得分:2)
我发现了一种更强大的方法:
如果您知道进入bottom
初始化的top
和GridSpec
kwargs,或者您知道 Figure
坐标中轴的边缘位置,您还可以使用一些奇特的“变换”魔法在Figure
坐标中指定ylabel位置。例如:
import matplotlib.transforms as mtransforms
bottom, top = .1, .9
f, a = plt.subplots(nrows=2, ncols=1, bottom=bottom, top=top)
avepos = (bottom+top)/2
a[0].yaxis.label.set_transform(mtransforms.blended_transform_factory(
mtransforms.IdentityTransform(), f.transFigure # specify x, y transform
)) # changed from default blend (IdentityTransform(), a[0].transAxes)
a[0].yaxis.label.set_position((0, avepos))
a[0].set_ylabel('Hello, world!')
...你应该看到标签仍然适当地调整左右以防止与ticklabels重叠,就像正常一样 - 但现在它将调整为总是 期望的子图。
此外,如果您甚至不使用set_position
,则ylabel默认会显示正好在数字的中间。我猜这是因为当最终绘制标签时,matplotlib
使用0.5作为y
坐标,而不检查基础坐标变换是否已更改。
答案 6 :(得分:2)
Matplotlib v3.4的新功能(尚未在pip中提供,clone from source)
supxlabel, supylabel
查看示例:
import matplotlib.pyplot as plt
for tl, cl in zip([True, False, False], [False, False, True]):
fig = plt.figure(constrained_layout=cl, tight_layout=tl)
gs = fig.add_gridspec(2, 3)
ax = dict()
ax['A'] = fig.add_subplot(gs[0, 0:2])
ax['B'] = fig.add_subplot(gs[1, 0:2])
ax['C'] = fig.add_subplot(gs[:, 2])
ax['C'].set_xlabel('Booger')
ax['B'].set_xlabel('Booger')
ax['A'].set_ylabel('Booger Y')
fig.suptitle(f'TEST: tight_layout={tl} constrained_layout={cl}')
fig.supxlabel('XLAgg')
fig.supylabel('YLAgg')
plt.show()
答案 7 :(得分:1)
如果通过为左下角的子图制作不可见标签为常用标签保留空间,效果会更好。从rcParams传入fontsize也很好。这样,公共标签将通过您的rc设置改变大小,并且还将调整轴以为公共标签留出空间。
fig_size = [8, 6]
fig, ax = plt.subplots(5, 2, sharex=True, sharey=True, figsize=fig_size)
# Reserve space for axis labels
ax[-1, 0].set_xlabel('.', color=(0, 0, 0, 0))
ax[-1, 0].set_ylabel('.', color=(0, 0, 0, 0))
# Make common axis labels
fig.text(0.5, 0.04, 'common X', va='center', ha='center', fontsize=rcParams['axes.labelsize'])
fig.text(0.04, 0.5, 'common Y', va='center', ha='center', rotation='vertical', fontsize=rcParams['axes.labelsize'])