How to add line based on slope and intercept in Matplotlib?
In R, there is a function called abline
in which a line can be drawn on a plot based on the specification of the intercept (first argument) and the slope (second argument). For instance,
plot(1:10, 1:10)
abline(0, 1)
where the line with an intercept of 0 and the slope of 1 spans the entire range of the plot. Is there such a function in Matplotlib?
A lot of these solutions are focusing on adding a line to the plot that fits the data. Here's a simple solution for adding an arbitrary line to the plot based on a slope and intercept.
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, '--')
I know this question is a couple years old, but since there is no accepted answer, I'll add what works for me.
You could just plot the values in your graph, and then generate another set of values for the coordinates of the best fit line and plot that over your original graph. For example, see the following code:
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()
As of 2021, in matplotlib 3.3.4, it supports drawing lines with slope value and a point.
fig, ax = plt.subplots()
ax.axline((0, 4), slope=3., color='C0', label='by slope')
ax.set_xlim(0, 1)
ax.set_ylim(3, 5)
ax.legend()
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')
I couldn't figure a way to do it without resorting to callbacks, but this seems to work fairly well.
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)