I'm working with a stacked area plot created by pandas. The screenshots shows one such typical plot (labels are deliberatly not shown):
The relevant code producing this plot is
fig, axes = plt.subplots(nrows=2, ncols=1)
coredata = nonzero.loc[:, nonzero.columns != 'Busy'].plot.area(figsize=(9, 8), ax=axes[0], colormap='jet')
where nonzero
is a larger dataframe. The issue is that there are too many columns leading to a crowded legend. Instead of moving the legend out of the picture I'd like to use matplotlib's events to tell me which element of the chart I'm hovering over.
def on_move(event):
if event.inaxes == coredata:
# help please
fig.canvas.mpl_connect("motion_notify_event", on_move)
The event fires exactly as desired but I have trouble extracting the area I'm hovering over (respectively its label). coredata.artists
is empty, coredata.lines
is a matplotlib.lines.Line2D element (supposedly too low level). How can I access the current area under the cursor in order to display its label?
Edit: following is a minimal example:
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()