Issue
I am trying to annotate a scatter plot in Python 2.7, with Matplotlib. Here is the plot code:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
df = pd.DataFrame(np.random.rand(5,3), columns=list('ABC'))
df.insert(0,'Annotation_Text',['ABC','DEF','GHI','JKL','mnop'])
q = 2
pqr = 1
# Scatter Plot:
x = df['A']
y = df.iloc[:,q]
plt.scatter(x, y, marker='o', label = df.columns.tolist()[q])
# Plot annotation:
plt.annotate(df.iloc[pqr,0]+', (%.2f, %.2f)' % (x.ix[pqr],y.ix[pqr]), xy=(x.ix[pqr], y.ix[pqr]), xycoords='data', xytext = (x.ix[pqr], y.ix[pqr]), textcoords='offset points', arrowprops=dict(arrowstyle='-|>'))
# Axes title/legend:
plt.xlabel('xlabel', fontsize=18)
plt.ylabel('ylabel', fontsize=16)
plt.legend(scatterpoints = 1)
plt.show()
As you can see, the main line is the line starting with plt.annotate(df.iloc[pqr,0]+', (%...............
.
I think that the main problem is with this part of the plt.annotate()
line: xytext = (x.ix[pqr], y.ix[pqr]), textcoords='offset points', arrowprops=dict(arrowstyle='-|>')
. From here, xytext = (x.ix[pqr], y.ix[pqr])
is just a tuple of the x and y co-ordinates of the data point to be annotated. Unfortunately, this is placing the annotation right at the data point, which I do not want. I want to leave some blank space between the data point and the annotation text.
Also, I am having a problem with the arrow and annotation that this line is producing. See below.
Problems:
- Currently, the annotation text is overlapping the arrow. The annotation text is too close to the data point. I don't want it to be so close.
- Also the arrow is pointing from right to left. I don't think I asked it to plot the arrow from right-to-left, so I don't know why it is plotting the arrow in this direction.
Is there a way to control the text annotation so that there is no overlap with the data point? Also, how do I change the arrow direction from right-to-left to the either a) the best
direction or b) from left-to-right?
Solution
In plt.annotate(...)
, xy
gives the position of the data you want to point at (one end of the arrow) and xytext
gives the position of your text. In your code, they are overlapping because you specified the same positions for xy
and xytext
. Try this instead (for example):
plt.annotate(df.iloc[pqr,0]+', (%.2f, %.2f)' % (x.ix[pqr], y.ix[pqr]), xy=(x.ix[pqr], y.ix[pqr]), xycoords='data', xytext=(x.ix[pqr], y.ix[pqr]+0.3), arrowprops=dict(arrowstyle='-|>'), horizontalalignment='center')
The arrow by default is pointing from the text to the data point. If you want to change the direction of the arrow, you can use arrowprops=dict(arrowstyle='<|-')
Answered By - Julien Spronck
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.