Python matplotlib 子图中的行和列标题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25812255/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 23:40:58  来源:igfitidea点击:

Row and column headers in matplotlib's subplots

pythonmatplotlibsubplot

提问by gozzilli

What's the best practise to add a row and a column header to a grid of subplots generated in a loop in matplotlib? I can think of a couple, but not particularly neat:

将行和列标题添加到在循环中生成的子图网格的最佳实践是matplotlib什么?我能想到几个,但不是特别整洁:

  1. For columns, with a counter to your loop you can use set_title()for the first row only. For rows this doesn't work. You would have to draw textoutside of the plots.
  2. You add an extra row of subplots on top and an extra column of subplots on the left, and draw text in the middle of that subplot.
  1. 对于列,使用循环计数器只能set_title()用于第一行。对于行,这不起作用。你将不得不text在情节之外画画。
  2. 您在顶部添加一排额外的子图,在左侧添加一列额外的子图,并在该子图的中间绘制文本。

Can you suggest a better alternative?

你能提出更好的选择吗?

enter image description here

在此处输入图片说明

采纳答案by Joe Kington

There are several ways to do this. The easy way is to exploit the y-labels and titles of the plot and then use fig.tight_layout()to make room for the labels. Alternatively, you can place additional text in the right location with annotateand then make room for it semi-manually.

有几种方法可以做到这一点。简单的方法是利用绘图的 y 标签和标题,然后使用fig.tight_layout()为标签腾出空间。或者,您可以将附加文本放置在正确的位置,annotate然后半手动为其腾出空间。



If you don't have y-labels on your axes, it's easy to exploit the title and y-label of the first row and column of axes.

如果您的轴上没有 y 标签,则很容易利用轴第一行和第一列的标题和 y 标签。

import matplotlib.pyplot as plt

cols = ['Column {}'.format(col) for col in range(1, 4)]
rows = ['Row {}'.format(row) for row in ['A', 'B', 'C', 'D']]

fig, axes = plt.subplots(nrows=4, ncols=3, figsize=(12, 8))

for ax, col in zip(axes[0], cols):
    ax.set_title(col)

for ax, row in zip(axes[:,0], rows):
    ax.set_ylabel(row, rotation=0, size='large')

fig.tight_layout()
plt.show()

enter image description here

在此处输入图片说明



If you do have y-labels, or if you prefer a bit more flexibility, you can use annotateto place the labels. This is more complicated, but allows you to have individual plot titles, ylabels, etc in addition to the row and column labels.

如果您确实有 y 标签,或者您更喜欢灵活一点,则可以使用annotate来放置标签。这更复杂,但除了行和列标签外,还允许您拥有单独的图标题、ylabels 等。

import matplotlib.pyplot as plt
from matplotlib.transforms import offset_copy


cols = ['Column {}'.format(col) for col in range(1, 4)]
rows = ['Row {}'.format(row) for row in ['A', 'B', 'C', 'D']]

fig, axes = plt.subplots(nrows=4, ncols=3, figsize=(12, 8))
plt.setp(axes.flat, xlabel='X-label', ylabel='Y-label')

pad = 5 # in points

for ax, col in zip(axes[0], cols):
    ax.annotate(col, xy=(0.5, 1), xytext=(0, pad),
                xycoords='axes fraction', textcoords='offset points',
                size='large', ha='center', va='baseline')

for ax, row in zip(axes[:,0], rows):
    ax.annotate(row, xy=(0, 0.5), xytext=(-ax.yaxis.labelpad - pad, 0),
                xycoords=ax.yaxis.label, textcoords='offset points',
                size='large', ha='right', va='center')

fig.tight_layout()
# tight_layout doesn't take these labels into account. We'll need 
# to make some room. These numbers are are manually tweaked. 
# You could automatically calculate them, but it's a pain.
fig.subplots_adjust(left=0.15, top=0.95)

plt.show()

enter image description here

在此处输入图片说明

回答by Alan Shteyman

The above answer works. Just not that in the second version of the answer, you have:

上面的答案有效。只是在答案的第二个版本中,您有:

for ax, row in zip(axes[:,0], rows):
    ax.annotate(col, xy=(0, 0.5), xytext=(-ax.yaxis.labelpad-pad,0),
                xycoords=ax.yaxis.label, textcoords='offset points',
                size='large', ha='right', va='center')

instead of:

代替:

for ax, row in zip(axes[:,0], rows):
    ax.annotate(row,xy=(0, 0.5), xytext=(-ax.yaxis.labelpad-pad,0),                    
                xycoords=ax.yaxis.label, textcoords='offset points',
                size='large', ha='right', va='center')