I’d like to add an arrow to a line plot with matplotlib
like in the plot below (drawn with pgfplots
).
How can I do (position and direction of the arrow should be parameters ideally)?
Here is some code to experiment.
JavaScript
x
7
1
from matplotlib import pyplot
2
import numpy as np
3
4
t = np.linspace(-2, 2, 100)
5
plt.plot(t, np.sin(t))
6
plt.show()
7
Thanks.
Advertisement
Answer
In my experience this works best by using annotate. Thereby you avoid the weird warping you get with ax.arrow
which is somehow hard to control.
EDIT: I’ve wrapped it into a little function.
JavaScript
1
46
46
1
from matplotlib import pyplot as plt
2
import numpy as np
3
4
5
def add_arrow(line, position=None, direction='right', size=15, color=None):
6
"""
7
add an arrow to a line.
8
9
line: Line2D object
10
position: x-position of the arrow. If None, mean of xdata is taken
11
direction: 'left' or 'right'
12
size: size of the arrow in fontsize points
13
color: if None, line color is taken.
14
"""
15
if color is None:
16
color = line.get_color()
17
18
xdata = line.get_xdata()
19
ydata = line.get_ydata()
20
21
if position is None:
22
position = xdata.mean()
23
# find closest index
24
start_ind = np.argmin(np.absolute(xdata - position))
25
if direction == 'right':
26
end_ind = start_ind + 1
27
else:
28
end_ind = start_ind - 1
29
30
line.axes.annotate('',
31
xytext=(xdata[start_ind], ydata[start_ind]),
32
xy=(xdata[end_ind], ydata[end_ind]),
33
arrowprops=dict(arrowstyle="->", color=color),
34
size=size
35
)
36
37
38
t = np.linspace(-2, 2, 100)
39
y = np.sin(t)
40
# return the handle of the line
41
line = plt.plot(t, y)[0]
42
43
add_arrow(line)
44
45
plt.show()
46
It’s not very intuitive but it works. You can then fiddle with the arrowprops
dictionary until it looks right.