21

In matplotlib we can draw lines using at least 2 methods:

  1. plt.plot

    plt.plot([1,2],[1,2],color='k',marker='o')
    
  2. Line2D method

    line = lines.Line2D([0.3,0.6],[0.9,0.3],linestyle='dashed',color='k')
    plt.axes().add_line(line)
    

I suspect both methods are the same in implementation of course. But anyway, it draws a line exactly between 2 stated points. Sometimes I need to extend line over those 2 points up to graph limits. Sure I can calculate it in form of y=ax+b, but does anybody know way easier?

Perfect case if I can just put some additional option, but I wasn't able to find it.

krouk
  • 305
  • 1
  • 2
  • 10
  • I think there is no direct way. Note that lines are drawn from arrays of n elements. that is, they are designed to be not straight. To extend a Line2D in a generic form you need to look at the two last pairs of points at the head and tail of the line. This is so strange that probably it was not taken into account for the special case of a two-point line where it does make sense – joaquin Feb 05 '12 at 14:36
  • +1 for `plt.plot([1,2],[1,2],color='k',marker='o')` – Sibbs Gambling Jul 30 '13 at 03:29

4 Answers4

7

After good lunch I was able to find a way using numpy.

def drawLine2P(x,y,xlims):
    xrange = np.arange(xlims[0],xlims[1],0.1)
    A = np.vstack([x, np.ones(len(x))]).T
    k, b = np.linalg.lstsq(A, y)[0]
    plt.plot(xrange, k*xrange + b, 'k')
krouk
  • 305
  • 1
  • 2
  • 10
3

Little late on this, but I just came across this while googling. I was also sick of not being able to do this in matplotlib, so I wrote abline_plot. It includes callbacks to update a 2D line if the axes limits are changed.

Search for the abline_plot examples in the link below.

http://statsmodels.sourceforge.net/devel/examples/generated/example_interactions.html

Documentation:

http://statsmodels.sourceforge.net/devel/generated/statsmodels.graphics.regressionplots.abline_plot.html#statsmodels.graphics.regressionplots.abline_plot

Implementation:

https://github.com/statsmodels/statsmodels/blob/master/statsmodels/graphics/regressionplots.py#L572

Edit: A simpler one that doesn't update

import matplotlib.pyplot as plt
from matplotlib import lines as mpl_lines

def slope_from_points(point1, point2):
    return (point2[1] - point1[1])/(point2[0] - point1[0])

def plot_secant(point1, point2, ax):
    # plot the secant
    slope = slope_from_points(point1, point2)
    intercept = point1[1] - slope*point1[0] 
    # update the points to be on the axes limits
    x = ax.get_xlim()
    y = ax.get_ylim()
    data_y = [x[0]*slope+intercept, x[1]*slope+intercept]
    line = mpl_lines.Line2D(x, data_y, color='red')
    ax.add_line(line)
    return ax.figure()
jseabold
  • 7,903
  • 2
  • 39
  • 53
3

Hope this helps

import matplotlib.pyplot as plt
# I am generating 2 random points, u might want to update these
x1,y1,x2,y2 = np.random.uniform(-1,1,4)
# make use of line equation to form function line_eqn(x) that generated y
line_eqn = lambda x : ((y2-y1)/(x2-x1)) * (x - x1) + y1        
# generate range of x values based on your graph
xrange = np.arange(-1.2,1.2,0.2)
# plot the line with generate x ranges and created y ranges
plt.plot(xrange, [ line_eqn(x) for x in xrange], color='k', linestyle='-', linewidth=2)
bicepjai
  • 1,615
  • 3
  • 17
  • 35
1

Way late, but here's the easiest answer for anyone who stumbles upon this like I did,

As of matplotlib 3.3, you can do this with plt.axline((x1, y1), (x2, y2)).

Austin Johnson
  • 697
  • 11
  • 23