190

I want to plot data, then create a new figure and plot data2, and finally come back to the original plot and plot data3, kinda like this:

import numpy as np
import matplotlib as plt

x = arange(5)
y = np.exp(5)
plt.figure()
plt.plot(x, y)

z = np.sin(x)
plt.figure()
plt.plot(x, z)

w = np.cos(x)
plt.figure("""first figure""") # Here's the part I need
plt.plot(x, w)

FYI How do I tell matplotlib that I am done with a plot? does something similar, but not quite! It doesn't let me get access to that original plot.

Community
  • 1
  • 1
Peter D
  • 3,055
  • 4
  • 22
  • 23

6 Answers6

178

If you find yourself doing things like this regularly it may be worth investigating the object-oriented interface to matplotlib. In your case:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(5)
y = np.exp(x)
fig1, ax1 = plt.subplots()
ax1.plot(x, y)
ax1.set_title("Axis 1 title")
ax1.set_xlabel("X-label for axis 1")

z = np.sin(x)
fig2, (ax2, ax3) = plt.subplots(nrows=2, ncols=1) # two axes on figure
ax2.plot(x, z)
ax3.plot(x, -z)

w = np.cos(x)
ax1.plot(x, w) # can continue plotting on the first axis

It is a little more verbose but it's much clearer and easier to keep track of, especially with several figures each with multiple subplots.

simonb
  • 2,577
  • 2
  • 17
  • 16
  • 3
    I prefer the object oriented approach as when I anticipate having many figures, it will be easier to keep track of them by using names rather than numbers. Thanks! – Peter D Aug 04 '11 at 04:37
  • 1
    But how can one change the label and axis limits with this approach. If I use `ax1.ylabel` it says that it is not found. Same with `fig1.ylabel` ... – George Datseris Aug 28 '16 at 07:45
  • 3
    @GeorgeDatseris The syntax is a little different. It's `ax1.set_xlabel("your x label")`, `ax1.set_ylabel("your y label")`, and `ax1.set_title("your title")`. – simonb Sep 12 '16 at 14:43
  • 1
    why did you use 111 ? – Yash Sodha May 16 '18 at 12:53
  • 2
    @yashSodha - that's a matlab-style specification of number of subplots (rows, col, index). But it's much easier now to use `plt.subplots(nrows, ncols)`. Have updated the example. – simonb Jun 10 '18 at 18:55
  • I upvoted you, cauz you're answer worked for me, thanks! But could you please add images to your answer, maybe more examples with different parameters? I mean, I had to look up the documentation to find best fit for my solution. Would have been really helpful to add images with different effects. – Kareem Jeiroudi Mar 29 '19 at 11:59
161

When you call figure, simply number the plot.

x = arange(5)
y = np.exp(5)
plt.figure(0)
plt.plot(x, y)

z = np.sin(x)
plt.figure(1)
plt.plot(x, z)

w = np.cos(x)
plt.figure(0) # Here's the part I need
plt.plot(x, w)

Edit: Note that you can number the plots however you want (here, starting from 0) but if you don't provide figure with a number at all when you create a new one, the automatic numbering will start at 1 ("Matlab Style" according to the docs).

agf
  • 160,324
  • 40
  • 275
  • 231
  • 4
    This appears to work in matplotlib's interactive mode, while the figure() ... add_subplot() method does not. Thanks! – chbrown Apr 02 '14 at 22:02
  • 1
    @SebMa Please don't change the code without understanding it. This answer was specifically about passing a number to `figure`, which you removed. The other things you changed were copied from the original post and not mistakes in my answer. – agf Jun 16 '18 at 15:02
  • @agf Hi, I removed the `1` inside `plt.figure(1)` because I thought the number was auto incremented and therefore not necessary. Sorry. – SebMa Jun 16 '18 at 16:35
21

However, numbering starts at 1, so:

x = arange(5)
y = np.exp(5)
plt.figure(1)
plt.plot(x, y)

z = np.sin(x)
plt.figure(2)
plt.plot(x, z)

w = np.cos(x)
plt.figure(1) # Here's the part I need, but numbering starts at 1!
plt.plot(x, w)

Also, if you have multiple axes on a figure, such as subplots, use the axes(h) command where h is the handle of the desired axes object to focus on that axes.

(don't have comment privileges yet, sorry for new answer!)

strpeter
  • 2,162
  • 3
  • 24
  • 44
Ross B.
  • 772
  • 6
  • 14
  • 12
    `0` works, _automatic_ numbering just start at `1`, if you don't give it a number at all. – agf Aug 02 '11 at 19:26
2

An easy way to plot separate frame for each iteration could be:

import matplotlib.pyplot as plt  
for grp in list_groups:
        plt.figure()
        plt.plot(grp)
        plt.show()

Then python will plot different frames.

Amirkhm
  • 722
  • 8
  • 12
1

One way I found after some struggling is creating a function which gets data_plot matrix, file name and order as parameter to create boxplots from the given data in the ordered figure (different orders = different figures) and save it under the given file_name.

def plotFigure(data_plot,file_name,order):
    fig = plt.figure(order, figsize=(9, 6))
    ax = fig.add_subplot(111)
    bp = ax.boxplot(data_plot)
    fig.savefig(file_name, bbox_inches='tight')
    plt.close()
emir
  • 301
  • 3
  • 6
1

The accepted answer here says use the object oriented interface (i.e. matplotlib), which is the way to go. The code for the answer does incorporate the (some of the) MATLAB-style interface (i.e. matplotib.pyplot) however.

There is the option of using solely the OOP method however, which can directly address the issue at hand and allow us to work with more than one figure at once:

import numpy as np
import matplotlib

x = np.arange(5)
y = np.exp(x)
first_figure      = matplotlib.figure.Figure()
first_figure_axis = first_figure.add_subplot()
first_figure_axis.plot(x, y)

z = np.sin(x)
second_figure      = matplotlib.figure.Figure()
second_figure_axis = second_figure.add_subplot()
second_figure_axis.plot(x, z)

w = np.cos(x)
first_figure_axis.plot(x, w)

display(first_figure) # Jupyter
display(second_figure)

This gives the user manual control over the figures, and avoids problems associated with pyplot's internal state supporting only a single figure, such as when you want to return a figure from a library function.

c z
  • 6,327
  • 3
  • 35
  • 50