如何解决如何使用 matplotlib 为 BrokenBarHCollection 对象在子图上创建悬停注释?
我目前有一个包含三个子图的图形,它们共享 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 对象来做到这一点。有人有什么想法吗?
子图目前的样子:
解决方法
有点不清楚您如何创建情节以及它的外观。下面的方法为每个小条分配一个标签。 broken_barh
对整个集合只能有一个标签,因此不是绘制 ax.broken_barh()
,而是创建单独的矩形,每个矩形都有自己的标签。另一种可能性是也为每个矩形分配单独的颜色(下面的示例假设最多 20 种颜色)。
在这种情况下,mplcursors
default 生成带有标签、光标的 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()
关于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)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。