在matplotlib上按列对数据点进行交互式注释

时间:2019-03-18 12:46:29

标签: python matplotlib

我是matplotlib,python和编程的新手。我一直在寻找这个问题的答案已有一段时间了,但一无所获。也许我不是在问合理的问题。
我有不同类型的绘图(绘图,散点图,plot_date,条形图等),每个轴有多个绘图,我在鼠标悬停时进行交互式注释。到目前为止,我一直在注释单个点(或条)。这就是代码的样子(在this answer上找到注释部分并对其进行了修改):

tabs = [{'SOUTH CAROLINA': 1662, 'IDAHO': 10343, 'VIRGINIA': 9689, 'KANSAS': 3634, 'NEBRASKA': 5024, 'TEXAS': 5134},
    {'SOUTH CAROLINA': 8015, 'IDAHO': 57541, 'VIRGINIA': 54272, 'KANSAS': 20370, 'NEBRASKA': 29011, 'TEXAS': 29910},
    {'SOUTH CAROLINA': 15000, 'IDAHO': 40000, 'VIRGINIA': 40000, 'KANSAS': 25000, 'NEBRASKA': 20000, 'TEXAS': 25000}]

vals = len(tabs)
xticks = np.arange(len(tabs[0]))
xlabels = list(tabs[0].keys())

fig, ax = plt.subplots(figsize=(8, 5))

plots = []
for i in range(len(tabs)):
    plots.append(
                ax.bar(
                        xticks - 0.7 / 2. + i / float(vals) * 0.7,
                        list(tabs[i].values()),
                        width=0.7/float(vals),
                        align='edge',
                        label=i
                    )
                )

# annotation template
annot = ax.annotate(
                    "",
                    xy = (0,0),
                    xytext = (10, 20),
                    textcoords = "offset points",
                    arrowprops = dict(arrowstyle = 'wedge', fc = 'black')
                    )

annot.set_visible(False)

# update annotation with bar data
def update_annot(i, bar):
    x = bar.get_x() + bar.get_width() / 2.
    y = bar.get_y() + bar.get_height()
    annot.xy = (x, y)
    text = f'{list(tabs[0].keys())[i]}: {y}'
    annot.set_text(text)
    annot.set_bbox(
                dict(
                    boxstyle='round',
                    lw=0,
                    alpha=0.8
                    )
                )


# activate annotation on hover
def hover(event):
    vis = annot.get_visible()
    if event.inaxes:
        for i, plot in enumerate(plots):
            for bar in plot:
                cont, _ = bar.contains(event)
                if cont:
                    update_annot(i, bar)
                    annot.set_visible(True)
                    fig.canvas.draw_idle()
                    return
    if vis:
        annot.set_visible(False)
        fig.canvas.draw_idle()

ax.set(title='title', xlabel='xlabel', ylabel='ylabel')
ax.set_xticks(xticks)
ax.set_xticklabels(xlabels, rotation=45)
ax.legend()
ax.grid(axis='y')
fig.tight_layout()

fig.canvas.mpl_connect("motion_notify_event", hover)
plt.show()

This is what I get when I run this script.
当我将鼠标悬停在其中一个栏上时,会看到一个带有x和y值的文本框。 但是现在我想用相同的x值注释所有点,这样,如果将鼠标悬停在其中的一个上,其余所有注释都将被注释。也就是说,在示例图像中,当我将鼠标悬停在代表任意状态的所有3列中时,都希望对其进行注释。
我尝试通过使用绘图对象列表上的zip()对每列进行分组,但是随后我无法一次显示多个注释。将列分组到列表中是不好的,因为它们不是matplotlib对象,并且不能在事件上被选择,并且遍历它们显然会一次选择一个。 任何帮助都感激不尽!

0 个答案:

没有答案