Flèche sur un tracé en ligne avec matplotlib

j'aimerais ajouter une flèche à une ligne de terrain avec matplotlib comme dans le graphique ci-dessous (tiré avec pgfplots).

enter image description here

Comment puis-je faire (la position et la direction de la flèche devraient être des paramètres idéalement)?

voici du code à expérimenter.

from matplotlib import pyplot
import numpy as np

t = np.linspace(-2, 2, 100)
plt.plot(t, np.sin(t))
plt.show()

Merci.

18
demandé sur cjorssen 2015-12-01 13:17:40

3 réponses

D'après mon expérience, ceci fonctionne le mieux en utilisant annoter. Ainsi, vous évitez le gauchissement bizarre que vous obtenez avec ax.arrow ce qui est difficile à contrôler.

EDIT: Je l'ai enveloppé dans une petite fonction.

from matplotlib import pyplot as plt
import numpy as np


def add_arrow(line, position=None, direction='right', size=15, color=None):
    """
    add an arrow to a line.

    line:       Line2D object
    position:   x-position of the arrow. If None, mean of xdata is taken
    direction:  'left' or 'right'
    size:       size of the arrow in fontsize points
    color:      if None, line color is taken.
    """
    if color is None:
        color = line.get_color()

    xdata = line.get_xdata()
    ydata = line.get_ydata()

    if position is None:
        position = xdata.mean()
    # find closest index
    start_ind = np.argmin(np.absolute(xdata - position))
    if direction == 'right':
        end_ind = start_ind + 1
    else:
        end_ind = start_ind - 1

    line.axes.annotate('',
        xytext=(xdata[start_ind], ydata[start_ind]),
        xy=(xdata[end_ind], ydata[end_ind]),
        arrowprops=dict(arrowstyle="->", color=color),
        size=size
    )


t = np.linspace(-2, 2, 100)
y = np.sin(t)
# return the handle of the line
line = plt.plot(t, y)[0]

add_arrow(line)

plt.show()

Ce n'est pas très intuitif, mais il fonctionne. Vous pouvez ensuite jouer avec le arrowprops dictionnaire jusqu'à ce qu'il ressemble à droite.

11
répondu thomas 2016-10-13 11:40:40

il suffit d'ajouter un plt.arrow():

from matplotlib import pyplot as plt
import numpy as np

# your function
def f(t): return np.sin(t)

t = np.linspace(-2, 2, 100)
plt.plot(t, f(t))
plt.arrow(0, f(0), 0.01, f(0.01)-f(0), shape='full', lw=0, length_includes_head=True, head_width=.05)
plt.show()

EDIT: modification des paramètres de la flèche pour inclure la position et la direction de la fonction à dessiner.

enter image description here

8
répondu adrianus 2015-12-01 12:14:01

ce n'est Pas la plus belle solution, mais devrait fonctionner:

import matplotlib.pyplot as plt
import numpy as np


def makeArrow(ax,pos,function,direction):
    delta = 0.0001 if direction >= 0 else -0.0001
    ax.arrow(pos,function(pos),pos+delta,function(pos+delta),head_width=0.05,head_length=0.1)

fun = np.sin
t = np.linspace(-2, 2, 100)
ax = plt.axes()
ax.plot(t, fun(t))
makeArrow(ax,0,fun,+1)

plt.show()
4
répondu elzell 2015-12-01 10:37:26