Manish
Manish

Reputation: 23

Tooltips or datapoint labels for Matplot mulitline plot

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?

enter image description here

Here is the revised imagine after the help from @r-beginners enter image description here

Any help?

Thanks Manish

Upvotes: 0

Views: 137

Answers (1)

r-beginners
r-beginners

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()

enter image description here

Upvotes: 1

Related Questions