Распечатать легенду во всплывающем окне для диаграммы стека - PullRequest
0 голосов
/ 17 июня 2020

Я пытаюсь построить большое количество кривых в стеке с помощью matplotlib, используя python. Чтобы прочитать график, мне нужно показать легенды, но если я покажу его с помощью метода legend, мой график будет нечитаемым (из-за количества легенд и их размера).


I обнаружили, что mplcursors может помочь мне сделать это с помощью всплывающего окна на самом графике. Он работает с "простыми" графиками, но не с stackplot.

Вот предупреждающее сообщение со стековыми графиками:

/usr/lib/python3.7/site-packages/mplcursors/_pick_info.py:141: UserWarning: Pick support for PolyCollection is missing.
  warnings.warn(f"Pick support for {type(artist).__name__} is missing.")

И вот код, связанный с этим ошибка (это всего лишь подтверждение концепции):

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


data = np.outer(range(10), range(1, 5))

timestamp = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

tmp = list()
tmp.append(data[:, 0])
tmp.append(data[:, 1])
tmp.append(data[:, 2])
tmp.append(data[:, 3])
print(data)
print(tmp)

fig, ax = plt.subplots()
ax.stackplot(timestamp, tmp, labels=('curve1', 'line2', 'curvefever', 'whatever'))
ax.legend()

mplcursors.cursor()

cursor = mplcursors.cursor(hover=True)


@cursor.connect("add")
def on_add(sel):
    print(sel)
    label = sel.artist.get_label()
    sel.annotation.set(text=label)


plt.show()

У вас есть идея, как это исправить, или вы знаете другой способ сделать что-то подобное?

1 Ответ

1 голос
/ 17 июня 2020

Непонятно, почему mplcursors не принимает диаграмму стека. Но вы можете воспроизвести поведение с более примитивной функциональностью matplotlib:

import matplotlib.pyplot as plt
import numpy as np

def update_annot(label, x, y):
    annot.xy = (x, y)
    annot.set_text(label)

def on_hover(event):
    visible = annot.get_visible()
    is_outside_of_stackplot = True
    if event.inaxes == ax:
        for coll, label in zip(stckplt, labels):
            contained, _ = coll.contains(event)
            if contained:
                update_annot(label, event.x, event.y)
                annot.set_visible(True)
                is_outside_of_stackplot = False
    if is_outside_of_stackplot and visible:
        annot.set_visible(False)
    fig.canvas.draw_idle()

data = np.random.randint(1, 5, size=(4, 40))

fig, ax = plt.subplots()
labels = ('curve1', 'line2', 'curvefever', 'whatever')
stckplt = ax.stackplot(range(data.shape[1]), data, labels=labels)
ax.autoscale(enable=True, axis='x', tight=True)
# ax.legend()

annot = ax.annotate("", xy=(0, 0), xycoords="figure pixels",
                    xytext=(20, 20), textcoords="offset points",
                    bbox=dict(boxstyle="round", fc="yellow", alpha=0.6),
                    arrowprops=dict(arrowstyle="->"))
annot.set_visible(False)
plt.connect('motion_notify_event', on_hover)
plt.show()

example plot

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