Как заставить метки появляться при наведении курсора на точку на нескольких осях? - PullRequest
1 голос
/ 28 апреля 2019

Я пытаюсь показать метку наведения на matplotlib с несколькими осями.

Я использую python 3.6.8 с matplotlib 3.0.3

У моего графика есть несколько осей, и я посмотрел пример из этого поста:

Возможно ли появление ярлыков при наведении курсора на точку в matplotlib?

Но ничего не происходит (не вижу этикеток).

Вот мой код:

import matplotlib.pyplot as plt
import numpy as np; np.random.seed(1)

x = np.sort(np.random.rand(15))
y = np.sort(np.random.rand(15))
y2 = np.sort(np.random.rand(15))

fig = plt.figure()
ax1 = plt.subplot(2, 2, 1)
line, = plt.plot(x,y)
ax1.grid(True)

ax2 = ax1.twinx()
ax2.plot(x, y2, color='green')
ax2.tick_params(axis='y', labelcolor='green')

annot = ax1.annotate("", xy=(0,0), xytext=(-20,20),textcoords="offset points",
                    bbox=dict(boxstyle="round", fc="w"),
                    arrowprops=dict(arrowstyle="->"))
annot.set_visible(False)

def update_annot(ind):
    x,y = line.get_data()
    annot.xy = (x[ind["ind"][0]], y[ind["ind"][0]])
    text = "x = {}\ny= {}".format(x[ind["ind"][0]], y[ind["ind"][0]])
    annot.set_text(text)
    annot.get_bbox_patch().set_alpha(0.4)


def hover(event):
    vis = annot.get_visible()
    if event.inaxes == ax1:
        cont, ind = line.contains(event)
        if cont:
            update_annot(ind)
            annot.set_visible(True)
            fig.canvas.draw_idle()
        else:
            if vis:
                annot.set_visible(False)
                fig.canvas.draw_idle()

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

plt.show()

когда я отключаю (комментирует) вторую ось (ax2), я вижу метки.

Как отобразить метки наведения при использовании нескольких осей?

1 Ответ

1 голос
/ 28 апреля 2019

Проблема действительно в том, что события запускаются только для одной из сдвоенных осей.Поэтому, если вы хотите пометить содержимое обеих осей, вам необходимо мультиплексировать разметку, то есть создать две аннотации, по одной для каждой оси, и настроить код таким образом, чтобы обе аннотации были потенциально видимыми.

Это может выглядеть какследует:

import matplotlib.pyplot as plt
import numpy as np; np.random.seed(1)

x = np.sort(np.random.rand(15))
y = np.sort(np.random.rand(15))
y2 = np.sort(np.random.rand(15))

fig = plt.figure()
ax1 = plt.subplot(2, 2, 1)
line1, = plt.plot(x,y)
ax1.grid(True)

ax2 = ax1.twinx()
line2, = ax2.plot(x, y2, color='green')
ax2.tick_params(axis='y', labelcolor='green')

annots = []
for ax in [ax1, ax2]:
    annot = ax1.annotate("", xy=(0,0), xytext=(-20,20),textcoords="offset points",
                        bbox=dict(boxstyle="round", fc="w", alpha=0.4),
                        arrowprops=dict(arrowstyle="->"))
    annot.set_visible(False)
    annots.append(annot)

annot_dic = dict(zip([ax1, ax2], annots))
line_dic = dict(zip([ax1, ax2], [line1, line2]))

def update_annot(line, annot, ind):
    x,y = line.get_data()
    annot.xy = (x[ind["ind"][0]], y[ind["ind"][0]])
    text = "x = {}\ny= {}".format(x[ind["ind"][0]], y[ind["ind"][0]])
    annot.set_text(text)

def hover(event):

    if event.inaxes in [ax1, ax2]:
        for ax in [ax1, ax2]:
            cont, ind = line_dic[ax].contains(event)
            annot = annot_dic[ax]
            if cont:
                update_annot(line_dic[ax], annot, ind)
                annot.set_visible(True)
                fig.canvas.draw_idle()
            else:
                if annot.get_visible():
                    annot.set_visible(False)
                    fig.canvas.draw_idle()

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

plt.show()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...