5

I am trying to label multiple maximum but unable to display them properly. Also the label is appearing too far from the point overlapping with the legend.

import matplotlib.pyplot as plt
import numpy as np

x1,y1= np.loadtxt('MaxMin1.txt', dtype=str, unpack=True)

x1 = x1.astype(int)
y1 = y1.astype(float)

x2,y2= np.loadtxt('MaxMin2.txt', dtype=str, unpack=True)

x2 = x2.astype(int)
y2 = y2.astype(float)

x3,y3= np.loadtxt('MaxMin3.txt', dtype=str, unpack=True)

x3 = x3.astype(int)
y3 = y3.astype(float)

#-------------------------------------------------------------
def annot_max(x,y, ax=None):
    xmax = x[np.argmax(y)]
    ymax = y.max()
    text= "x={:.3f}, y={:.3f}".format(xmax, ymax)
    if not ax:
        ax=plt.gca()
    bbox_props = dict(boxstyle="square,pad=0.3", fc="w", ec="k", lw=0.72)
    arrowprops=dict(arrowstyle="->",connectionstyle="angle,angleA=0,angleB=60")
    kw = dict(xycoords='data',textcoords="axes fraction",
              arrowprops=arrowprops, bbox=bbox_props, ha="left", va="top")
    ax.annotate(text, xy=(xmax, ymax), xytext=(0.94,0.96), **kw)


#-------------------------------------------------------------

fig=plt.figure()
fig.show()
ax=fig.add_subplot(111)

ax.plot(x1,y1,c='b',ls='-',label='Recovery',fillstyle='none')
ax.plot(x2,y2,c='g',ls='-',label='Normal')
ax.plot(x3,y3,c='r',ls='-',label='No-Recovery')
annot_max(x1,y1)
annot_max(x2,y2)
annot_max(x3,y3)
plt.legend(loc=1)

# naming the x axis 
plt.xlabel('<------Instances(count)------>') 
# naming the y axis 
plt.ylabel('Acceleration (m/sq.sec)') 
# giving a title to my graph 
plt.title('Fall Detection Comparison graph')

plt.show()

And the output I got Output Graph I am just beginning with python so very small hint may not be understandable by me.Please help.

2
  • I would use textcoords="offset points" and xytext=(25,12). Of course you can play around with the values to see what fits. Commented Dec 21, 2018 at 12:34
  • Will give it a try and update result here. Commented Dec 21, 2018 at 18:38

1 Answer 1

4

You need yo change function annot_max. First of all, all your labels appear in the same place according to xytext=(0.94,0.96). You have to specify label position according to coordinates of xmax and ymax as below.

Then change textcoords to data value to manipulate a label position according to data not axes fraction. In my example xytext=(xmax+.5,ymax+5) means that location of label box will shifted by +.5 point from xmax and +5 points by ymax (you have to use your own values according to your data).

But I recommend to place your labels manually since you have 3 maximum (specify a location of every label box in argument xytext like xytext=(100,40) - your 1st maximum).

Matplotlib can not avoid overlapping of text boxes automatically.

To squeeze label box you can place text in two rows, i.e., text= "x={:.3f},\ny={:.3f}".format(xmax, ymax).

import matplotlib.pyplot as plt
import numpy as np

x1=np.array([1,2,3,4,5,6,7,8,9,10])
x2 = x1[:]
x3 = x1[:]
y1=np.array([1,2,3,100,5,6,7,8,9,10])
y2=np.array([50,2,3,4,5,6,7,8,9,10])
y3=np.array([1,2,3,4,5,6,75,8,9,10])

#-------------------------------------------------------------
def annot_max(x,y, ax=None):
    xmax = x[np.argmax(y)]
    ymax = y.max()
    text= "x={:.3f}, y={:.3f}".format(xmax, ymax)
    if not ax:
        ax=plt.gca()
    bbox_props = dict(boxstyle="square,pad=0.3", fc="w", ec="k", lw=0.72)
    arrowprops=dict(arrowstyle="->",connectionstyle="angle,angleA=0,angleB=60")
    kw = dict(xycoords='data',textcoords="data",
              arrowprops=arrowprops, bbox=bbox_props, ha="left", va="top")
    ax.annotate(text, xy=(xmax, ymax), xytext=(xmax+.5,ymax+5), **kw)


#-------------------------------------------------------------

fig=plt.figure()
fig.show()
ax=fig.add_subplot(111)

ax.plot(x1,y1,c='b',ls='-',label='Recovery',fillstyle='none')
ax.plot(x2,y2,c='g',ls='-',label='Normal')
ax.plot(x3,y3,c='r',ls='-',label='No-Recovery')
annot_max(x1,y1)
annot_max(x2,y2)
annot_max(x3,y3)
plt.legend(loc=1)

# naming the x axis 
plt.xlabel('<------Instances(count)------>') 
# naming the y axis 
plt.ylabel('Acceleration (m/sq.sec)') 
# giving a title to my graph 
plt.title('Fall Detection Comparison graph')

plt.show()

enter image description here

Sign up to request clarification or add additional context in comments.

3 Comments

So the only change I see is xytext=(xmax+.5,ymax+5). However when I am running this the max labels go out of the visibility area. I am sharing the data files if that helps, in my OP.
No, change textcoords="data" in arrowprops.
you made a misprint. Take my code, load your data and change xytext position as your desire.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.