0

我目前有一个包含三个子图的图形,它们都共享 y 轴但不共享 x 轴。对于每个子图,我使用创建 BrokenBarHCollection 的 for 循环生成数据点。我使用的 for 循环如下(函数“f”只是为每个子图创建 xranges 和 yrange):

for c in f(t):
    axis[1].add_collection(c)

现在,我希望用户能够将鼠标悬停在该子图中的某些点上,并显示有关他们悬停的内容的注释。但是,我需要显示的标签最初并未用于创建子图,因此我创建了一个列表,其中包含我需要的所有标签,另一个列表包含我想要指定的 x 轴上的所有点。由于它们是矩形(使用 BrokenBarHCollection),第二个列表中的点是矩形的中间)。y 范围仅为 0。我后来创建了一个字典,其中标签是键,点是值,并弄清楚如何使用以下代码在子图中生成注释:

for keys, values in gene_dict.items():
    y = 0
    annot = axs[1].annotate(keys, xy = (values, y), fontsize = 4) 

这是结果字典:

{'YFL067': 2074.5, 'YFL041': 49352.5, 'YPT1': 56193.5, 'PAU5': 99435.0, 'YFL019': 100497.0, 'SMX2': 103801.5, 'YFL015': 106649.5, 'HSP12': 107304.5, 'YFL012': 110789.5, 'AUA1': 114958.0, 'WWM1': 115252.0, 'YPI1': 152424.0, 'MIC19': 166370.5, 'YFR012': 168579.0, 'RPL29': 222135.5, 'CDC26': 225896.0, 'YMR31': 247177.5}

所以,我的问题是如何使用我生成的标签和沿 x 轴的点来创建悬停注释?我在这里看到过使用 mplcursors 的帖子,但是当我这样做时,什么也没有发生:

mplcursors.cursor(axs[1]).connect("add", lambda sel: sel.annot.set_text(keys[sel.target.index]))

我想我必须创建一个 onHover 事件函数,但我不确定如何使用 BrokenBarHCollection 对象来做到这一点。有人有什么想法吗?

子图当前的样子:

在此处输入图像描述

4

1 回答 1

0

有点不清楚你是如何创建你的情节以及它的样子。下面的方法为每个小条分配一个标签。Abroken_barh整个集合只能有一个标签,因此ax.broken_barh()创建了单独的矩形而不是绘图,每个矩形都有自己的标签。另一种可能性是也为每个矩形分配单独的颜色(下面的示例假设最多 20 种颜色)。

在这种情况下,mplcursors默认会生成带有标签、光标的 x 和 y 位置的注释。您可以更改默认注释,例如仅使用标签。

请注意,mplcursors.cursor(..., hover=True)悬停时会显示注释。默认只在点击时显示注解。

import matplotlib.pyplot as plt
import mplcursors
import numpy as np

gene_dict = {'YFL067': 2074.5, 'YFL041': 49352.5, 'YPT1': 56193.5, 'PAU5': 99435.0, 'YFL019': 100497.0, 'SMX2': 103801.5, 'YFL015': 106649.5, 'HSP12': 107304.5, 'YFL012': 110789.5, 'AUA1': 114958.0, 'WWM1': 115252.0, 'YPI1': 152424.0, 'MIC19': 166370.5, 'YFR012': 168579.0, 'RPL29': 222135.5, 'CDC26': 225896.0, 'YMR31': 247177.5}
color_dict = { key:color for key, color in zip(gene_dict.keys(), plt.cm.tab20.colors )}

fig, ax = plt.subplots()

for y in range(10, 51, 10):
    keys = np.random.choice(list(gene_dict.keys()), 5, replace=False)
    width = 3000
    for key in keys:
        ax.add_patch(plt.Rectangle((gene_dict[key] - width / 2, y), width, 9,
                                   color=color_dict[key], label=key))
ax.relim() # needed to update the xlim and ylim when using add_patch
ax.autoscale()

mplcursors.cursor(hover=True).connect("add", lambda sel: sel.annotation.set_text(sel.artist.get_label()))
plt.show()

broken_barh 的悬停注释

关于mplcursors.cursor(...).connect("add", lambda sel: ...). lambda是一种快速编写短函数(无名称)的方法,因此可以将其用作另一个函数的参数。代码等价于:

def update_annotation(sel):
    """ update the annotation belonging to the current selected item (sel) """
    # get the label of the graphical element that is selected
    label = sel.artist.get_label()
    # change the text of the annotation
    sel.annotation.set_text(label)

# create an mplcursor object that shows an annotation while hovering
cursor = mplcursors.cursor(hover=True)
# call the function "update_annotation" each time a new element gets hovered over
cursor.connect("add", update_annotation)
于 2021-04-14T21:31:59.140 回答