goz*_*lli 63 python matplotlib subplot
将行和列标题添加到循环中生成的子图网格中的最佳做法是matplotlib
什么?我能想到一对,但不是特别整洁:
set_title()
第一行.对于行,这不起作用.你必须text
在地块之外画画.你能建议一个更好的选择吗?
Joe*_*ton 78
有几种方法可以做到这一点.简单的方法是利用图表的y标签和标题,然后用来fig.tight_layout()
为标签腾出空间.或者,您可以将其他文本放在正确的位置,annotate
然后半手动为其腾出空间.
如果您的轴上没有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()
Run Code Online (Sandbox Code Playgroud)
如果您有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()
Run Code Online (Sandbox Code Playgroud)
根据 Joe Kington 的回答,我提出了一个可以在代码库中重用的函数:
\n它接受以下参数:
\nfig
:包含要处理的轴的图形row_headers
, col_headers
:作为标题的字符串序列row_pad
, col_pad
:int
调整填充的值rotate_row_headers
: 是否将行标题旋转90\xc2\xb0**text_kwargs
: 转发给ax.annotate(...)
函数在这里,例子如下:
\nimport numpy as np\n\ndef add_headers(\n fig,\n *,\n row_headers=None,\n col_headers=None,\n row_pad=1,\n col_pad=5,\n rotate_row_headers=True,\n **text_kwargs\n):\n # Based on https://stackoverflow.com/a/25814386\n\n axes = fig.get_axes()\n\n for ax in axes:\n sbs = ax.get_subplotspec()\n\n # Putting headers on cols\n if (col_headers is not None) and sbs.is_first_row():\n ax.annotate(\n col_headers[sbs.colspan.start],\n xy=(0.5, 1),\n xytext=(0, col_pad),\n xycoords="axes fraction",\n textcoords="offset points",\n ha="center",\n va="baseline",\n **text_kwargs,\n )\n\n # Putting headers on rows\n if (row_headers is not None) and sbs.is_first_col():\n ax.annotate(\n row_headers[sbs.rowspan.start],\n xy=(0, 0.5),\n xytext=(-ax.yaxis.labelpad - row_pad, 0),\n xycoords=ax.yaxis.label,\n textcoords="offset points",\n ha="right",\n va="center",\n rotation=rotate_row_headers * 90,\n **text_kwargs,\n )\n
Run Code Online (Sandbox Code Playgroud)\n这是在标准网格上使用它的示例(没有轴跨越多行/列):
\nimport random\nimport matplotlib.pyplot as plt\n\nmosaic = [\n ["A0", "A1", "A2"],\n ["B0", "B1", "B2"],\n]\nrow_headers = ["Row A", "Row B"]\ncol_headers = ["Col 0", "Col 1", "Col 2"]\n\nsubplots_kwargs = dict(sharex=True, sharey=True, figsize=(10, 6))\nfig, axes = plt.subplot_mosaic(mosaic, **subplots_kwargs)\n\nfont_kwargs = dict(fontfamily="monospace", fontweight="bold", fontsize="large")\nadd_headers(fig, col_headers=col_headers, row_headers=row_headers, **font_kwargs)\n\nplt.show()\n
Run Code Online (Sandbox Code Playgroud)\n\n如果某些轴跨越多个行/列,则正确分配行/列标题会变得不太简单。\n我没有设法从函数内部对其进行排序,但注意给定的 和 参数row_headers
就col_headers
足以让它轻松工作:
mosaic = [\n ["A0", "A1", "A1", "A2"],\n ["A0", "A1", "A1", "A2"],\n ["B0", "B1", "B1", "B2"],\n]\n\nrow_headers = ["A", "A", "B"] # or\nrow_headers = ["A", None, "B"] # or\nrow_headers = {0: "A", 2: "B"}\n\ncol_headers = ["0", "1", "1", "2"] # or\ncol_headers = ["0", "1", None, "2"] # or\ncol_headers = {0: "0", 1: "1", 3: "2"}\n\nfig, axes = plt.subplot_mosaic(mosaic, **subplots_kwargs)\nadd_headers(fig, col_headers=col_headers, row_headers=row_headers, **font_kwargs)\nplt.show()\n
Run Code Online (Sandbox Code Playgroud)\n\n
归档时间: |
|
查看次数: |
26948 次 |
最近记录: |