我正在处理由熊猫创建的堆积区域图。屏幕截图显示了一个这样的典型图(标签未明确显示): 生成此图的相关代码是
fig, axes = plt.subplots(nrows=2, ncols=1)
coredata = nonzero.loc[:, nonzero.columns != 'Busy'].plot.area(figsize=(9, 8), ax=axes[0], colormap='jet')
其中nonzero
是一个更大的数据帧。问题是有太多的列导致拥挤的传说。我没有将图例移出图片,而是想使用matplotlib的事件来告诉我图表中的哪个元素悬停在上面。
def on_move(event):
if event.inaxes == coredata:
# help please
fig.canvas.mpl_connect("motion_notify_event", on_move)
事件完全按照需要触发,但我无法提取我悬停在其上的区域(分别是其标签)。 coredata.artists
为空,coredata.lines
是matplotlib.lines.Line2D元素(假设级别太低)。如何访问光标下的当前区域以显示其标签?
编辑以下是一个最小的例子:
from pandas import DataFrame, Series
from matplotlib import pyplot as plt
# mock data
d = {'one' : Series([1., 2., 3.], index=['a', 'b', 'c']),
'two' : Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd']),
'three': Series([0.5, 0.2, 0.3, 0.1], index=['a', 'b', 'c', 'd']),
'four': Series([3., 2., 1., 0.3], index=['a', 'b', 'c', 'd']),
}
df = DataFrame(d)
fig, axes = plt.subplots()
chart = df.plot.area(ax=axes)
# create and initially hide annotation
annot = axes.annotate("", xy=(0,0), xytext=(-20,20),textcoords="offset points",
bbox=dict(boxstyle="round", fc="w"))
annot.set_visible(False)
def on_move(event):
if event.inaxes == chart:
pass # help plz: how do I best check I currently hover over one, two, three or four?
print(event.xdata, event.ydata)
fig.canvas.mpl_connect("motion_notify_event", on_move)
plt.show()
答案 0 :(得分:1)
就像悬停分散时一样,请参阅例如here或here您需要检查是否有任何集合包含mouseevent。为此,您将查看感兴趣的集合,进行检查,如果成功,可以在列表中添加标识符。
which = []
for i,c in enumerate(axes.collections):
if c.contains(event)[0]:
which.append(i)
然后,您可以使用此列表绘制一个新图例,其中仅包含该列表中标识的集合。由于重绘画布很昂贵并且可能会减慢应用程序的速度,因此很少会尝试这样做。在移动鼠标的过程中,很多时候都会出现完全相同的结果,因此我们可以存储它,只有在需要更改时才创建新的图例。
from pandas import DataFrame, Series
from matplotlib import pyplot as plt
# mock data
d = {'one' : Series([1., 2., 3.], index=['a', 'b', 'c']),
'two' : Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd']),
'three': Series([0.5, 0.2, 0.3, 0.1], index=['a', 'b', 'c', 'd']),
'four': Series([3., 2., 1., 0.3], index=['a', 'b', 'c', 'd']),
}
df = DataFrame(d)
fig, axes = plt.subplots()
df.plot.area(ax=axes, legend=False)
# create and initially hide annotation
annot = axes.annotate("", xy=(0,0), xytext=(-20,20),textcoords="offset points",
bbox=dict(boxstyle="round", fc="w"))
annot.set_visible(False)
last = [None]
def on_move(event):
if event.inaxes == axes:
which = []
for i,c in enumerate(axes.collections):
if c.contains(event)[0]:
which.append(i)
if which != last[0]:
last[0] = which
axes.legend([axes.collections[i] for i in which],
[df.columns[i] for i in which])
fig.canvas.draw_idle()
fig.canvas.mpl_connect("motion_notify_event", on_move)
plt.show()