用鼠标悬停时用 matplotlib 注释绘图的线条
Annotate lines of a plot with matplotlib when hover with mouse
我想在用鼠标悬停时在绘图上注释不同的线,这里用点也是一样的方法Possible to make labels appear when hovering over a point in matplotlib?
我尝试将此代码改写如下:
import matplotlib.pyplot as plt
import numpy as np; np.random.seed(1)
y = np.random.rand(4,15)
x = [np.arange(15) for i in range(len(y))]
names = np.array(list("ABCD"))
fig, ax = plt.subplots()
lines = []
for i in range(len(names)):
lines.append(ax.plot(x[i],y[i]))
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 = line.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:
for line in lines:
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()
问题是当我将鼠标悬停在绘图上时出现以下错误:
AttributeError: 'list' object has no attribute 'contains'
我该如何解决这个问题?
您不能盲目复制用于 scatter()
的代码并用于 plot()
,因为返回的艺术家完全不同。
此外,您看到的错误的根本原因是 plot()
returns 艺术家列表(即使绘制单行)。我已经修改了你的代码以提供一些应该接近你想要的东西:
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(1)
y = np.random.rand(4, 15)
x = [np.arange(15) for i in range(len(y))]
names = np.array(list("ABCD"))
fig, ax = plt.subplots()
lines = []
for i in range(len(names)):
l, = ax.plot(x[i], y[i], label=names[i])
lines.append(l)
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(line, idx):
posx, posy = [line.get_xdata()[idx], line.get_ydata()[idx]]
annot.xy = (posx, posy)
text = f'{line.get_label()}: {posx:.2f}-{posy:.2f}'
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:
for line in lines:
cont, ind = line.contains(event)
if cont:
update_annot(line, ind['ind'][0])
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()
我想在用鼠标悬停时在绘图上注释不同的线,这里用点也是一样的方法Possible to make labels appear when hovering over a point in matplotlib?
我尝试将此代码改写如下:
import matplotlib.pyplot as plt
import numpy as np; np.random.seed(1)
y = np.random.rand(4,15)
x = [np.arange(15) for i in range(len(y))]
names = np.array(list("ABCD"))
fig, ax = plt.subplots()
lines = []
for i in range(len(names)):
lines.append(ax.plot(x[i],y[i]))
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 = line.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:
for line in lines:
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()
问题是当我将鼠标悬停在绘图上时出现以下错误:
AttributeError: 'list' object has no attribute 'contains'
我该如何解决这个问题?
您不能盲目复制用于 scatter()
的代码并用于 plot()
,因为返回的艺术家完全不同。
此外,您看到的错误的根本原因是 plot()
returns 艺术家列表(即使绘制单行)。我已经修改了你的代码以提供一些应该接近你想要的东西:
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(1)
y = np.random.rand(4, 15)
x = [np.arange(15) for i in range(len(y))]
names = np.array(list("ABCD"))
fig, ax = plt.subplots()
lines = []
for i in range(len(names)):
l, = ax.plot(x[i], y[i], label=names[i])
lines.append(l)
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(line, idx):
posx, posy = [line.get_xdata()[idx], line.get_ydata()[idx]]
annot.xy = (posx, posy)
text = f'{line.get_label()}: {posx:.2f}-{posy:.2f}'
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:
for line in lines:
cont, ind = line.contains(event)
if cont:
update_annot(line, ind['ind'][0])
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()