web-dev-qa-db-fra.com

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

Dans R, il existe une fonction appelée abline dans laquelle une ligne peut être dessinée sur un tracé en fonction de la spécification de l'interception (premier argument) et de la pente (second argument). Par exemple,

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

où la ligne avec une intersection de 0 et la pente de 1 couvre toute la gamme de la parcelle. Existe-t-il une telle fonction dans Matplotlib?

40
hatmatrix

Un grand nombre de ces solutions consistent à ajouter une ligne au tracé qui correspond aux données. Voici une solution simple pour ajouter une ligne arbitraire au tracé en fonction d'une pente et d'une interception.

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, '--')
43
David Marx

Je sais que cette question date de quelques années, mais comme il n’ya pas de réponse acceptée, je vais ajouter ce qui fonctionne pour moi.

Vous pouvez simplement tracer les valeurs dans votre graphique, puis générer un autre ensemble de valeurs pour les coordonnées de la droite la mieux ajustée et les représenter sur votre graphique d'origine. Par exemple, voir 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()
30
Steve

Je ne pouvais pas trouver un moyen de le faire sans recourir aux 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)
9
ali_m
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')
6
mok0

Je suppose que dans le cas de (intercept, slope) sur (0, 1), la fonction suivante pourrait être utilisée et étendue pour prendre en charge d’autres pentes et intersections, mais ne sera pas réinitialisée si les limites de l’axe sont modifiées ou si l’autoscale est réactivé.

def abline():
    gca = plt.gca()
    gca.set_autoscale_on(False)
    gca.plot(gca.get_xlim(),gca.get_ylim())

import matplotlib.pyplot as plt
plt.scatter(range(10),range(10))
abline()
plt.draw()
4
hatmatrix

Voici une solution de contournement possible: supposons que mes coordonnées d'interception soient stockées sous la forme x_intercept et y_intercept, et que la pente (m) soit enregistrée sous la forme my_slope qui a été trouvée à l'aide de la célèbre équationm = (y2-y1)/(x2-x1), ou de quelque manière que vous ayez réussi à le trouver. 

En utilisant l’autre équation générale célèbre pour une ligney = mx + q, je définis la fonction find_second_point qui calcule d’abord leq(puisque m , x et y sont connus) et calcule ensuite un autre point aléatoire appartenant à cette ligne. 

Une fois que j'ai les deux points (le x_intercept, y_intercept initial et le new_x, new_y trouvé récemment), je trace simplement le segment à travers ces deux points. Voici le code:

import numpy as np
import matplotlib.pyplot as plt

x_intercept = 3  # invented x coordinate
y_intercept = 2  # invented y coordinate
my_slope = 1  # invented slope value

def find_second_point(slope,x0,y0):
    # this function returns a point which belongs to the line that has the slope 
    # inserted by the user and that intercepts the point (x0,y0) inserted by the user
    q = y0 - (slope*x0)  # calculate q
    new_x = x0 + 10  # generate random x adding 10 to the intersect x coordinate
    new_y = (slope*new_x) + q  # calculate new y corresponding to random new_x created

    return new_x, new_y  # return x and y of new point that belongs to the line

# invoke function to calculate the new point
new_x, new_y = find_second_point(my_slope , x_intercept, y_intercept )

plt.figure(1)  # create new figure
plt.plot((x_intercept, new_x),(y_intercept, new_y), c='r', label='Segment')
plt.scatter(x_intercept, y_intercept, c='b', linewidths=3, label='Intercept')
plt.scatter(new_x, new_y, c='g', linewidths=3, label='New Point')
plt.legend()  # add legend to image

plt.show()

voici l'image générée par le code:

result image

0
Tommaso Di Noto