Можно ли сделать метки появляются при наведении указателя мыши на точку в matplotlib?
Я использую matplotlib, чтобы сделать точечные графики. Каждая точка на точечной диаграмме связана с именованным объектом. Я хотел бы иметь возможность видеть имя объекта при наведении курсора на точку на точечной диаграмме, связанной с этим объектом. В частности, было бы неплохо иметь возможность быстро увидеть названия точек, которые являются выбросами. Самое близкое, что я смог найти во время поиска здесь, - это команда annotate, но, похоже, она создает фиксированную метку сюжет. К сожалению, с количеством точек, которые у меня есть, график рассеяния будет нечитаемым, если я помечу каждую точку. Кто-нибудь знает способ создания меток, которые появляются только тогда, когда курсор находится в непосредственной близости от этой точки?
6 ответов:
кажется, ни один из других ответов здесь на самом деле ответить на этот вопрос. Итак, вот код, который использует scatter и аннотации на зависания по точкам раскидать.
import matplotlib.pyplot as plt import numpy as np; np.random.seed(1) x = np.random.rand(15) y = np.random.rand(15) names = np.array(list("ABCDEFGHIJKLMNO")) c = np.random.randint(1,5,size=15) norm = plt.Normalize(1,4) cmap = plt.cm.RdYlGn fig,ax = plt.subplots() sc = plt.scatter(x,y,c=c, s=100, cmap=cmap, norm=norm) annot = ax.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): pos = sc.get_offsets()[ind["ind"][0]] annot.xy = pos text = "{}, {}".format(" ".join(list(map(str,ind["ind"]))), " ".join([names[n] for n in ind["ind"]])) annot.set_text(text) annot.get_bbox_patch().set_facecolor(cmap(norm(c[ind["ind"][0]]))) annot.get_bbox_patch().set_alpha(0.4) def hover(event): vis = annot.get_visible() if event.inaxes == ax: cont, ind = sc.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()
потому что люди вдруг также хотят использовать это решение для линии
plot
вместо разброса, следующее будет то же самое решение дляplot
(который немного работает иначе.)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)) names = np.array(list("ABCDEFGHIJKLMNO")) norm = plt.Normalize(1,4) cmap = plt.cm.RdYlGn fig,ax = plt.subplots() line, = plt.plot(x,y, marker="o") annot = ax.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 = "{}, {}".format(" ".join(list(map(str,ind["ind"]))), " ".join([names[n] for n in ind["ind"]])) annot.set_text(text) annot.get_bbox_patch().set_alpha(0.4) def hover(event): vis = annot.get_visible() if event.inaxes == ax: 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()
в случае если кто-то ищет решение для столбцовые диаграммы, пожалуйста, обратитесь к, например,ответ.
Я знаю, что это старый вопрос, но я продолжал прибывать сюда, ища решение, чтобы навести (не нажимать) линию.
import matplotlib.pyplot as plt fig = plt.figure() plot = fig.add_subplot(111) # create some curves for i in range(4): plot.plot( [i*1,i*2,i*3,i*4], gid=i) def on_plot_hover(event): for curve in plot.get_lines(): if curve.contains(event)[0]: print "over %s" % curve.get_gid() fig.canvas.mpl_connect('motion_notify_event', on_plot_hover) plt.show()
от http://matplotlib.sourceforge.net/examples/event_handling/pick_event_demo.html:
from matplotlib.pyplot import figure, show import numpy as npy from numpy.random import rand if 1: # picking on a scatter plot (matplotlib.collections.RegularPolyCollection) x, y, c, s = rand(4, 100) def onpick3(event): ind = event.ind print 'onpick3 scatter:', ind, npy.take(x, ind), npy.take(y, ind) fig = figure() ax1 = fig.add_subplot(111) col = ax1.scatter(x, y, 100*s, c, picker=True) #fig.savefig('pscoll.eps') fig.canvas.mpl_connect('pick_event', onpick3) show()
- этот рецепт рисует аннотацию при выборе точки данных:http://scipy-cookbook.readthedocs.io/items/Matplotlib_Interactive_Plotting.html .
- этот рецепт рисует подсказку, но для этого требуется wxPython: точечные и линейные подсказки в matplotlib?
небольшое редактирование на примере, приведенном в http://matplotlib.org/users/shell.html:
import numpy as np import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111) ax.set_title('click on points') line, = ax.plot(np.random.rand(100), '-', picker=5) # 5 points tolerance def onpick(event): thisline = event.artist xdata = thisline.get_xdata() ydata = thisline.get_ydata() ind = event.ind print 'onpick points:', zip(xdata[ind], ydata[ind]) fig.canvas.mpl_connect('pick_event', onpick) plt.show()
это строит прямую линию участок, как Sohaib просил
mpld3 решить его для меня. РЕДАКТИРОВАТЬ (ДОБАВЛЕННЫЙ КОД):
import matplotlib.pyplot as plt import numpy as np import mpld3 fig, ax = plt.subplots(subplot_kw=dict(axisbg='#EEEEEE')) N = 100 scatter = ax.scatter(np.random.normal(size=N), np.random.normal(size=N), c=np.random.random(size=N), s=1000 * np.random.random(size=N), alpha=0.3, cmap=plt.cm.jet) ax.grid(color='white', linestyle='solid') ax.set_title("Scatter Plot (with tooltips!)", size=20) labels = ['point {0}'.format(i + 1) for i in range(N)] tooltip = mpld3.plugins.PointLabelTooltip(scatter, labels=labels) mpld3.plugins.connect(fig, tooltip) mpld3.show()
вы можете проверить этой пример
mplcursors работал на меня. mplcursors предоставляет интерактивную аннотацию для matplotlib. Он сильно вдохновлен mpldatacursor (https://github.com/joferkington/mpldatacursor), с гораздо более упрощенным API
import matplotlib.pyplot as plt import numpy as np import mplcursors data = np.outer(range(10), range(1, 5)) fig, ax = plt.subplots() lines = ax.plot(data) ax.set_title("Click somewhere on a line.\nRight-click to deselect.\n" "Annotations can be dragged.") mplcursors.cursor(lines) # or just mplcursors.cursor() plt.show()