Reputation: 23
I am trying to get tooltips or datapoint labels for matplotlib multiline plot..
I have this piece of data:
DateIndex Actual Prediction
0 2019-07-22 38.112534 44.709328
1 2019-07-23 38.293377 43.949799
2 2019-07-24 38.067326 43.779831
3 2019-07-25 37.193264 43.490322
4 2019-07-26 36.937077 43.118225
5 2019-07-29 36.394554 42.823986
6 2019-07-30 36.138367 42.699570
7 2019-07-31 39.152367 42.297470
8 2019-08-01 42.211578 44.002003
9 2019-08-02 42.045807 46.165192
10 2019-08-05 38.896175 46.307037
11 2019-08-06 34.495735 44.375160
12 2019-08-07 35.415005 42.012119
13 2019-08-08 34.902622 42.322872
14 2019-08-09 38.368725 42.143345
15 2019-08-12 40.403179 44.080429
16 2019-08-13 41.307377 45.192703
17 2019-08-14 37.780994 45.666252
18 2019-08-15 35.565704 43.773438
19 2019-08-16 35.942455 42.334888
and with this code:
import matplotlib.dates as mdates
plt.rcParams["figure.figsize"] = (20,8)
# market o sets a dot at each point, x="DateIndex" sets the X axis
ax = nbpActualPredictionDf.plot.line(x="DateIndex", marker = 'o')
plt.title('Actual vs Prediction using LSTM')
ax.set_xlabel('Date')
ax.set_ylabel('NBP Prices')
# this allows a margin to be kept around the plot
x0, x1, y0, y1 = plt.axis()
margin_x = 0.05 * (x1-x0)
margin_y = 0.05 * (y1-y0)
plt.axis((x0 - margin_x,
x1 + margin_x,
y0 - margin_y,
y1 + margin_y))
# hides major tick labels
# plt.setp(ax.get_xmajorticklabels(), visible=False)
# this allows us to write at each datapoint on x axis what date it is.
ax.xaxis.remove_overlapping_locs = False
# get the values of DateIndex and set our own minor labels using dd-mm format
dateIndexData = nbpActualPredictionDf['DateIndex']
# d is for numeric day, m is for abbr month and a is for abbr day of week
labels = [l.strftime('%d-%m\n%a') for l in dateIndexData]
# next line adds the labels, but note we need to add a [''] to add a blank value. this allows us to start on the 0,0 with a blank and avoid skipping a real date label later
ax.set_xticklabels(['']+labels, minor=True)
# Customize the major grid
ax.grid(which='major', linestyle='-', linewidth='0.5', color='red')
# Customize the minor grid
ax.grid(which='minor', linestyle=':', linewidth='0.5', color='grey')
ax.annotate(round(nbpActualPredictionDf.iloc[0,1],2),
xy=(115, 195), xycoords='figure pixels')
ax.annotate(round(nbpActualPredictionDf.iloc[1,1],2),
xy=(115*1.5, 195), xycoords='figure pixels')
ax.grid(True)
plt.show()
Whilst I get the graph to be correct, I want to be able to have labels at each data point. Or a tooltip. whichever is easier. I would prefer tooltips as it avoids the clutter, but can settle for a label with rounding of the data so that it takes less space
I looked up annotate but it seems not as straight forward as it looks. I mean, you will note 2 places where I added labels with a bit of effort to get the x and y coordinates, but how do I know what these are going to be?
Here is the revised imagine after the help from @r-beginners
Any help?
Thanks Manish
Upvotes: 0
Views: 137
Reputation: 35145
You can get the data for the annotations with the following code That acquisition is supported by a loop process. The other is to create and display a bounding box with ax.text()
. The way it is displayed is the same. This code modifies the official reference.
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(20,8),dpi=144)
ax = fig.add_subplot(111)
# plt.rcParams["figure.figsize"] = (20,8)
# market o sets a dot at each point, x="DateIndex" sets the X axis
# ax = nbpActualPredictionDf.plot.line(x="DateIndex", marker = 'o')
ann1 = ax.plot(nbpActualPredictionDf.DateIndex, nbpActualPredictionDf.Actual, marker='o')
ann2 = ax.plot(nbpActualPredictionDf.DateIndex, nbpActualPredictionDf.Prediction, marker='o')
plt.title('Actual vs Prediction using LSTM')
ax.set_xlabel('Date')
ax.set_ylabel('NBP Prices')
# this allows a margin to be kept around the plot
x0, x1, y0, y1 = plt.axis()
margin_x = 0.05 * (x1-x0)
margin_y = 0.05 * (y1-y0)
plt.axis((x0 - margin_x,
x1 + margin_x,
y0 - margin_y,
y1 + margin_y))
# hides major tick labels
# plt.setp(ax.get_xmajorticklabels(), visible=False)
# this allows us to write at each datapoint on x axis what date it is.
ax.xaxis.remove_overlapping_locs = False
# get the values of DateIndex and set our own minor labels using dd-mm format
dateIndexData = nbpActualPredictionDf['DateIndex']
# d is for numeric day, m is for abbr month and a is for abbr day of week
# labels = [l.strftime('%d-%m\n%a') for l in dateIndexData]
# next line adds the labels, but note we need to add a [''] to add a blank value. this allows us to start on the 0,0 with a blank and avoid skipping a real date label later
# ax.set_xticklabels(['']+labels, minor=True)
# Customize the major grid
ax.grid(which='major', linestyle='-', linewidth='0.5', color='red')
# Customize the minor grid
ax.grid(which='minor', linestyle=':', linewidth='0.5', color='grey')
# bounding box define
boxdic={'facecolor':'0.9',
'edgecolor':'0.6',
'boxstyle':'round',
'linewidth':1}
def autolabel(anns):
for an in anns:
xdata = an.get_xdata()
ydata = an.get_ydata()
for x,y in zip(xdata, ydata):
ax.annotate('{:.2f}'.format(y),
xy=(x, y),
xytext=(0, 3), # 3 points vertical offset
textcoords="offset points",
ha='center', va='bottom')
def boxlabel(anns):
for an in anns:
xdata = an.get_xdata()
ydata = an.get_ydata()
for x,y in zip(xdata, ydata):
ax.text(x, y+0.5, str("{:.2f}".format(y)), color="k", fontsize=8, bbox=boxdic)
autolabel(ann1)
boxlabel(ann2)
ax.grid(True)
plt.show()
Upvotes: 1