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?
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, '--')
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()
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)
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')
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()
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: