81 votes

Comment ajouter une ligne basée sur la pente et l'intercept dans Matplotlib ?

En R, il existe une fonction appelée abline dans lequel une ligne peut être tracée sur un graphique en fonction de la spécification de l'ordonnée à l'origine (premier argument) et de la pente (deuxième argument). Par exemple,

plot(1:10, 1:10)
abline(0, 1)

où la ligne dont l'ordonnée à l'origine est 0 et la pente 1 s'étend sur toute la plage du graphique. Existe-t-il une telle fonction dans Matplotlib ?

4 votes

Non, il n'y en a pas. Ce serait une fonction pratique à avoir. Il y a axvline , axvspan , axhline et axhspan qui sont des fonctions verticales et horizontales similaires, mais la méthode habituelle dans matplotlib consiste à tracer une ligne à la pente donnée (ce qui signifie que vous finirez par zoomer au-delà, si vous travaillez de manière interactive). La manière "correcte" de le faire (c'est-à-dire de manière à ce que la ligne s'étende toujours sur l'axe, peu importe où vous zoomez) est en fait un peu compliquée, bien que le cadre ( matplotlib.transforms ) est là.

1 votes

Oui, c'est malheureux... Matlab ne dispose pas non plus de cette fonction. D'un autre côté, les graphiques de R sont statiques (la fonction base système graphique pour lequel abline existe), donc moins de soucis à se faire (c'est une bonne et une mauvaise chose, je suppose).

108voto

David Marx Points 2393

Beaucoup de ces solutions se concentrent sur l'ajout d'une ligne au graphique qui correspond aux données. Voici une solution simple pour ajouter une ligne arbitraire au graphique à partir d'une pente et d'une ordonnée à l'origine.

import matplotlib.pyplot as plt 
import numpy as np    

def abline(slope, intercept):
    """Plot a line from slope and intercept"""
    axes = plt.gca()
    x_vals = np.array(axes.get_xlim())
    y_vals = intercept + slope * x_vals
    plt.plot(x_vals, y_vals, '--')

17 votes

Je ne peux pas croire que cette fonctionnalité n'est pas incluse directement dans matplotlib . Cela semble être la toute première chose à mettre en œuvre si l'on crée un tel paquet.

5 votes

@ijoseph Bienvenue dans le monde du partage et de l'entraide ! "Chaque bon travail de logiciel commence par gratter la démangeaison personnelle d'un développeur" - Eric S. Raymond. Allez-y et envoyez une demande de pull à la Projet Matplotlib !

1 votes

Juste un point mineur pour l'exhaustivité il faut import matplotlib.pyplot as plt import numpy as np au début du script.

39voto

Steve Points 791

Je sais que cette question date de quelques années, mais comme il n'y a pas de réponse reconnue, je vais ajouter ce qui fonctionne pour moi.

Vous pouvez simplement reporter les valeurs dans votre graphique, puis générer un autre ensemble de valeurs pour les coordonnées de la ligne de meilleur ajustement et les reporter sur votre graphique original. Par exemple, voyez le code suivant :

import matplotlib.pyplot as plt
import numpy as np

# Some dummy data
x = [1, 2, 3, 4, 5, 6, 7]
y = [1, 3, 3, 2, 5, 7, 9]

# Find the slope and intercept of the best fit line
slope, intercept = np.polyfit(x, y, 1)

# Create a list of values in the best fit line
abline_values = [slope * i + intercept for i in x]

# Plot the best fit line over the actual values
plt.plot(x, y, '--')
plt.plot(x, abline_values, 'b')
plt.title(slope)
plt.show()

12voto

mok0 Points 651
X = np.array([1, 2, 3, 4, 5, 6, 7])
Y = np.array([1.1,1.9,3.0,4.1,5.2,5.8,7])

scatter (X,Y)
slope, intercept = np.polyfit(X, Y, 1)
plot(X, X*slope + intercept, 'r')

10voto

lindelof Points 9802

Il semble que cette fonctionnalité fera partie de la version 3.3.0 :

matplotlib.axes.Axes.axline

Vous serez, par exemple, en mesure de tracer une ligne rouge à travers des points (0, 0) y (1, 1) en utilisant

axline((0, 0), (1, 1), linewidth=4, color='r')

9voto

ali_m Points 7185

Je n'ai pas réussi à trouver un moyen de le faire sans recourir à des rappels, mais cela semble fonctionner assez bien.

import numpy as np
from matplotlib import pyplot as plt

class ABLine2D(plt.Line2D):

    """
    Draw a line based on its slope and y-intercept. Additional arguments are
    passed to the <matplotlib.lines.Line2D> constructor.
    """

    def __init__(self, slope, intercept, *args, **kwargs):

        # get current axes if user has not specified them
        if not 'axes' in kwargs:
            kwargs.update({'axes':plt.gca()})
        ax = kwargs['axes']

        # if unspecified, get the current line color from the axes
        if not ('color' in kwargs or 'c' in kwargs):
            kwargs.update({'color':ax._get_lines.color_cycle.next()})

        # init the line, add it to the axes
        super(ABLine2D, self).__init__([], [], *args, **kwargs)
        self._slope = slope
        self._intercept = intercept
        ax.add_line(self)

        # cache the renderer, draw the line for the first time
        ax.figure.canvas.draw()
        self._update_lim(None)

        # connect to axis callbacks
        self.axes.callbacks.connect('xlim_changed', self._update_lim)
        self.axes.callbacks.connect('ylim_changed', self._update_lim)

    def _update_lim(self, event):
        """ called whenever axis x/y limits change """
        x = np.array(self.axes.get_xbound())
        y = (self._slope * x) + self._intercept
        self.set_data(x, y)
        self.axes.draw_artist(self)

0 votes

Petite amélioration : permuter les lignes : ax.figure.canvas.draw() et self._update_lim(None) pour que le tracé soit réellement mis à jour sans avoir à cliquer sur la fenêtre

0 votes

@tal Enfin sur ma version de matplotlib (1.4.3) il est nécessaire de rendre les axes parents au moins une fois avant d'appeler self.axes.draw_artist(self) sinon je reçois un AssertionError sur la ligne assert self._cachedRenderer is not None sur Axes.draw_artist . Vous pouvez toujours insérer un tirage supplémentaire après _update_lim a été appelé. En général, j'initialise le ABLine à l'intérieur d'une fonction de commodité qui le fait pour moi, plutôt que de l'instancier directement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X