19

I want to remove a specific line in a plot of multiple lines. Bellow is a given example which is not sufficient for me because it removes only the last plotted line and not the line that I want to remove. How can I do that? How can I address a specific line(by name, by number, by reference) throughout the program and delete that line?

self.axes.lines.remove(self.axes.lines[0])
Jomme
  • 1,256
  • 4
  • 14
  • 26

5 Answers5

36

Almost all of the plotting functions return a reference to the artist object created ex:

ln, = plot(x, y)  # plot actually returns a list of artists, hence the ,
im = imshow(Z)

If you have the reference you can remove an artist via the remove (doc) function ex:

ln.remove()
im.remove()
wwii
  • 23,232
  • 7
  • 37
  • 77
tacaswell
  • 84,579
  • 22
  • 210
  • 199
16

Edit: tacaswell's answer is better than mine

I keep my answer anyhow for the records (and because the upvotes are nice :wink:)


If you don't want to save the reference of all the lines explicitly but you know the index of the line that you want to remove, you can use the fact that maptplotlib stores them for you.

self.axes.lines

is a list of matplotlib.lines.Line2D. So to remove, e.g., the second line drawn you can do

self.axes.lines[1].remove()
Francesco Montesano
  • 8,485
  • 2
  • 40
  • 64
  • 4
    I strongly discourage this usage. It relies on a number of things that _should_ be internal details of Matplotlib and does not do the right thing if you do it twice. – tacaswell Aug 19 '17 at 22:38
  • This was the only thing that worked for me, thank you. – Arthur Dent Feb 27 '18 at 23:26
3

I had the same need and for me, it turned out to be tidier to add an id to the data series and remove it later by finding the series (collection) with the given id.

def add_series(x, id):
  plt.plot(x, gid = id)

def remove_series(id):
  for c in plt.collections: # possibly better to use: for c in plt.lines (see comment)
    if c.get_gid() == id:
      c.remove()
Community
  • 1
  • 1
Andrew
  • 4,574
  • 26
  • 31
0

The code generates step response for underdamped second order system. The code can also be used to illustrate overlaying of plots. The code generates and displays graphically, the response for two values of time constant parameter. The code also illustrates creation of comet in a for loop.

import numpy as np
import matplotlib.pyplot as plt

The following programme runs on version 3.6.
Code generates a pair of lines and the line 2 is removed in a for loop which
simulates a comet effect
pts=100
t2 = np.linspace(0.0,5.0,pts)
t2=(t2/50)
tm=t2*(10**3)
nz=t2.size
tc=np.linspace(0.8,2.5,2)
nz=tc.size
for n in range (nz):
    print(tc[n])
    resp = 1 - np.exp(-tc[n]*tm*10**-3*50) * np.cos(2*np.pi*50*tm*10**-3)
    for m in range(pts):
        plt.xlim(0,100)
        plt.ylim(0,2)
        plt.xlabel('Time,in milliseconds',fontsize=12)
        plt.ylabel('Respose',fontsize=12)
        plt.title('Underdamped Second Order System Step Response',fontsize=14)
        line1,=plt.plot(tm[0:m+1],resp[0:m+1],color='black',linewidth=0.2)
        line2,=plt.plot(tm[m],resp[m],marker='o',color='red',markersize=5)
        ax = plt.gca()
        plt.pause(0.02)
        ax.lines.remove(line2)
        plt.grid('on')
plt.show()
0

You can also use this for multiple subplots

subfig, subax = plt.subplots(3) 

def add_series(x, y0, y1, y2, gid):
    plt.figure(subfig.number)
    ln, = subax[0].plot(x, y0, gid=gid)
    ln, = subax[1].plot(x, y1, gid=gid)
    ln, = subax[2].plot(x, y2, gid=gid)
    plt.draw()

def remove_series(self, gid):
    plt.figure(subfig.number)
    for c0, c1, c2 in zip(subax[0].lines, subax[1].lines, subax[2].lines):
        if c0.get_gid() == gid:
            c0.remove()
        if c1.get_gid() == gid:
            c1.remove()
        if c2.get_gid() == gid:
            c2.remove()
    plt.draw()