Matplotlib 获取图例标记的坐标

Posted

技术标签:

【中文标题】Matplotlib 获取图例标记的坐标【英文标题】:Matplotlib getting coordinates of legend markers 【发布时间】:2021-09-17 15:33:31 【问题描述】:

这是我第一次在这里提问。所以请告诉我是否有任何问题。

所以我正在尝试创建一个综合生成图表的数据集,以训练神经网络找到图表不同元素的边界框 - 图例框、图表标题、轴标签等。这就是我管理的部分去做。

接下来我需要创建一个从不同图例条目到其相应数据点的映射。我需要为围绕不同句柄和文本的边界框创建注释,如下所示:

我已尝试查看文档,但找不到任何相关功能。使用matplotlib.artist.getp() 研究图例的属性也让我一无所获。

fig, ax = plt.subplots(figsize=(12, 4))
x_vals = np.linspace(0, 5, 5)
y_vals = np.random.uniform(size=(5,))

ax.plot(x_vals, y_vals, label='line1')
ax.plot(x_vals, y_vals + np.random.randn(), label='line2')
leg = ax.legend()
ax.set_label('Label via method')

matplotlib.artist.getp(leg)

Output:
    agg_filter = None
    alpha = None
    animated = False
    bbox_to_anchor = TransformedBbox(     Bbox(x0=0.125, y0=0.125, x1=0...
    children = [<matplotlib.offsetbox.VPacker object at 0x7f3582d...
    clip_box = None
    clip_on = True
    clip_path = None
    contains = None
    default_handler_map = <class 'matplotlib.container.StemContainer'>: <ma...
    figure = Figure(864x288)
    frame = FancyBboxPatch(640.55,203.64;60.625x33)
    frame_on = True
    gid = None
    label = 
    legend_handler_map = <class 'matplotlib.container.StemContainer'>: <ma...
    lines = [<matplotlib.lines.Line2D object at 0x7f35834f4400...
    patches = <a list of 0 Patch objects>
    path_effects = []
    picker = None
    rasterized = None
    sketch_params = None
    snap = None
    texts = <a list of 2 Text objects>
    title = Text(0,0,'None')
    transform = IdentityTransform()
    transformed_clip_path_and_affine = (None, None)
    url = None
    visible = True
    window_extent = Bbox(x0=640.5500000000001, y0=203.64, x1=701.17500...
    zorder = 5

任何帮助将不胜感激。请告诉我是否需要任何澄清。谢谢

【问题讨论】:

【参考方案1】:

我花了整整 30 分钟的时间试图弄清楚一些事情。我确信有一个更简单的方法,但这是我整理的一些东西,希望对你有所帮助

import matplotlib.pyplot as plt; plt.ion()
from matplotlib.patches import Rectangle as rect

fig, ax = plt.subplots()
ax.plot([0,1],[4,6],label='test')
leg = ax.legend(edgecolor='w', loc='upper left')
leg.get_frame().set_alpha(0)
line = leg.get_lines()[0]
plt.draw()
plt.pause(0.001)

#all of this is based on pixel coordinates in the figure
(lx0, ly0, lx1, ly1) = (leg.get_window_extent().x0,
                       leg.get_window_extent().y0,
                       leg.get_window_extent().x1,
                       leg.get_window_extent().y1)
(mx0, my0, mx1, my1) = (line.get_window_extent(fig).x0,
                       line.get_window_extent(fig).y0,
                       line.get_window_extent(fig).x1,
                       line.get_window_extent(fig).y1)
(ax0, ay0, ax1, ay1) = (ax.get_window_extent().x0,
                       ax.get_window_extent().y0,
                       ax.get_window_extent().x1,
                       ax.get_window_extent().y1)
#convert pixel coords to graphical coords
x0, x1 = ax.get_xlim()
y0, y1 = ax.get_ylim()
ratex = (x1-x0) / (ax1-ax0)
ratey = (y1-y0) / (ay1-ay0)
newx0 = (mx0 - ax0) * ratex + x0
newx1 = (mx1 - ax0) * ratex + x0
newy0 = (my0 - ay0) * ratey + y0 - 0.05
newy1 = (my1 - ay0) * ratey + y0 + 0.05
#box around legend marker
ax.add_patch(rect((newx0, newy0), newy1-newy0, newx1-newx0, edgecolor='k', alpha=0.5, facecolor='w'))
#convert pixel coords to graphical coords
tx0 = mx1
tx1 = lx1
ty0 = ly0
ty1 = ly1
newx0 = (tx0 - ax0) * ratex + x0
newx1 = (tx1 - ax0) * ratex + x0
newy0 = (ty0 - ay0) * ratey + y0
newy1 = (ty1 - ay0) * ratey + y0
#box around legend txt
ax.add_patch(rect((newx0, newy0), newy1-newy0, newx1-newx0, edgecolor='k', alpha=0.5, facecolor='w'))

这会产生以下情节:

我不是 100% 确定为什么这些框是关闭的,但是您可以修改它以使其以某种方式工作...您也可以使用它来获取图例条目的坐标,并从这些坐标绘制一个向量到坐标在相应的数据线上

【讨论】:

非常感谢最初的指导。对于此答案中提到的每个元素,我能够使用leg._legend_handle_box.get_children() 后跟get_window_extent() 获得更精确的坐标:***.com/a/44072076/13430696 lmao 什么任务..很高兴你想通了

以上是关于Matplotlib 获取图例标记的坐标的主要内容,如果未能解决你的问题,请参考以下文章

Matplotlib 图例:标记上方的标签

Matplotlib:在图例中移动标记位置

matplotlib 图例标记仅一次

通过 matplotlib 图例中的标记删除线

通过 matplotlib 图例中的标记删除线

如何删除 matplotlib 图例上的线条/标记?