Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何将字母放置在子批次的角部,包括轴标签(而不是轴的角部)_Python_Matplotlib_Text_Transform_Subplot - Fatal编程技术网

Python 如何将字母放置在子批次的角部,包括轴标签(而不是轴的角部)

Python 如何将字母放置在子批次的角部,包括轴标签(而不是轴的角部),python,matplotlib,text,transform,subplot,Python,Matplotlib,Text,Transform,Subplot,我想用左上角的字母(A、B、C,…)标记子批次,这些字母要么与标签对齐,要么与子批次的实际角对齐(而不是轴) 如果子地块的宽度不同,我不能再使用轴变换坐标中有偏移的文本,因为这会导致每个子地块的距离不同。所以我通常使用偏移变换。但是,如果标签的宽度不同,这就不起作用了。我目前也在关注每个绘图的偏移量,但这还不够好 这就是我到目前为止所做的: 导入matplotlib.pyplot作为plt 从matplotlib导入转换 将numpy作为np导入 图=plt.图(figsize=(5,2),受限

我想用左上角的字母(A、B、C,…)标记子批次,这些字母要么与标签对齐,要么与子批次的实际角对齐(而不是轴)

如果子地块的宽度不同,我不能再使用轴变换坐标中有偏移的文本,因为这会导致每个子地块的距离不同。所以我通常使用偏移变换。但是,如果标签的宽度不同,这就不起作用了。我目前也在关注每个绘图的偏移量,但这还不够好

这就是我到目前为止所做的:

导入matplotlib.pyplot作为plt
从matplotlib导入转换
将numpy作为np导入
图=plt.图(figsize=(5,2),受限布局=真)
gs=图添加网格规格(1,3,宽度比=[1,2,3])
轴=[图为范围(3)内的i添加子批次(gs[i])]
ylabels=[“平面标签”、“更大的标签”、“甚至更大的标签”]
标签=[“A”、“B”、“C”]
scaledtrans=transforms.scaledtransation(-0.4,0,fig.dpi\u scale\u trans)
对于ax、ylabel、zip中的标签(轴、ylabel、标签):
ax.set_ylabel(ylabel)
ax.text(0,1,标签,fontsize=12,fontwweight=“bold”,va=“bottom”,ha=“left”,
transform=ax.transAxes+scaledtrans)
正如您在下图中所看到的,标签与轴脊椎的距离相同,但我希望它们与ylabel的左边缘或子地块的角对齐,在本例中,这将与ylabel水平重合。不过没有transSubplot,只有transAxes和transFigure


似乎是将标签放置在各个轴的紧边界框的边缘

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(5, 2), constrained_layout=True)
gs = fig.add_gridspec(1, 3, width_ratios=[1, 2, 3])
axes = [fig.add_subplot(gs[i]) for i in range(3)]

ylabels = ["flat label", "bigger\nlabel", "even\nbigger\nlabel"]
labels = ["A", "B", "C"]

for ax, ylabel in zip(axes, ylabels):
    ax.set_ylabel(ylabel)

fig.canvas.draw()

for ax, label in zip(axes, labels):
    bbox = ax.get_tightbbox(fig.canvas.get_renderer())
    fig.text(bbox.x0, bbox.y1, label, fontsize=12, fontweight="bold", va="top", ha="left",
             transform=None)

plt.show()

这样做的一个明显缺点是不能在事后更改图形大小。更好的一点可能是首先转换回图形坐标,还可以对绘制事件使用回调来更新坐标

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(5, 2), constrained_layout=True)
gs = fig.add_gridspec(1, 3, width_ratios=[1, 2, 3])
axes = [fig.add_subplot(gs[i]) for i in range(3)]

ylabels = ["flat label", "bigger\nlabel", "even\nbigger\nlabel"]
labels = ["A", "B", "C"]

for ax, ylabel in zip(axes, ylabels):
    ax.set_ylabel(ylabel)

fig.canvas.draw()

axlabels = [fig.text(0,0, label, fontsize=12, fontweight="bold", va="top", ha="left")
            for ax, label in zip(axes, labels)]

def update_labels(evt=None):
    trans = fig.transFigure.inverted()
    for ax, label in zip(axes, axlabels):
        bbox = ax.get_tightbbox(fig.canvas.get_renderer())
        label.set_position(trans.transform_point([bbox.x0, bbox.y1]))

update_labels()
cid = fig.canvas.mpl_connect("draw_event", update_labels)

plt.show()

请注意,这里的一个关键要素是
fig.text
不参与受约束的_布局机制。因此,此类解决方案仅适用于图形边界内的位置。

任何子地块都是轴。所以这里的概念有点难理解。我认为OP希望标签位于gridspec的边缘,而不是相对于轴。不幸的是,这很难获得先验知识(受约束的_布局在绘图时进行定位)。我的方法是触发一个抽签,获得标签的位置,然后以这种方式将文本放置在图坐标中。通过查看
ax.\u layoutbox
,还可以获得由约束的\u布局确定的轴边界框。很明显,这是私人的,所以如果它改变了,不要抱怨;-)是的,这是正确的,我试图确定布局框角落的位置,但这些似乎包含理论变量,而不是图形坐标中的已解变量。那么,您将如何在地物坐标中检索y标签位置呢?
get_window_extent
应该可以做到……我尝试了
axes[0]。yaxis.get_label().get_position()
,但它返回
(21.736577796,0.5)
,而这不在地物坐标中。标签的变换似乎是一种混合仿射变换,但我不知道如何从中获得图形坐标第一种变换非常适合静态图像;不幸的是,第二种方法在高dpi监视器上不起作用。我不知道有什么简单的方法可以使标签在调整大小时跟踪布局框的边缘。您可以制作一个轴来放置标签,然后制作一个轴定位器,在绘制时查找布局框的边缘。这似乎是一个很大的工作,我不相信这是普遍可取的;大多数情况下,子地块标签要么在轴本身的左上角,要么在轴的标题中。@JodyKlymak可以在绘制事件上使用回调来重新定位标签。也许您可以测试更新后的第二个解决方案是否也适用于“高dpi”设备?谢谢,这正是我想要的:)在显示坐标中添加更多元素之前,我不知道Tightbox和调用draw,所以这一切都非常有帮助。我通常会为出版物创建像素完美的打印,这样我就不需要考虑调整大小时会发生什么。