3

What's the best practice to create multiple separate plots using matplotlib, so they can be called later or output into a pdf report? I'm a bit unclear as to how to do this in a way that retains each plot in memory (like we could with dataframes) for later reference.

Suppose we have this code:

%pylab inline
x1 = np.random.randn(50)*100
y1 = np.random.randn(50)*100
x2 = np.random.randn(50)*100
y2 = np.random.randn(50)*100

and the intent is to create 2 separate plots of (x1,y1) and (x2,y2) and 'save' them in some way to be referenced later. the intent is to be able to output these into a PDF (perhaps via reportlab). the relationship between "figures", "subplots" and "axes" is confusing to me and not sure what is optimal for this purpose. i started with an approach like:

plt.figure(1, figsize=(8, 6))
plt.subplot(211)
plt.scatter(x1, y1, c = 'r', alpha = 0.3)

plt.subplot(212)
plt.scatter(x2, y2, c = 'k', alpha = 0.7)
plt.show()

which does technically work, but i'm not sure how i can refer to these later. also, i am using a small example here for illustration, but in practice i may have many more of these.

smci
  • 32,567
  • 20
  • 113
  • 146
laszlopanaflex
  • 1,836
  • 3
  • 23
  • 34
  • Not exactly on spot, but almost a duplicate. See [this](http://stackoverflow.com/questions/11469336/what-is-the-difference-between-pylab-and-pyplot). You likely want to `pyplot`. But you can still use `pylab`, and call plt.figure(N) subsequently, to select again your `N`-th figure and plot on that. – gg349 Mar 10 '16 at 18:15
  • thanks, i actually am using pylot in my import. i have to include the %pylab inline bit because otherwise, the pictures do not show up – laszlopanaflex Mar 10 '16 at 18:20
  • Then use sth like `fig,ax = plt.subplots(); ax.plot([1,2,3]), fig.show()`. You can plot on the axis `ax` in as many places as you need in your code, and only in the end call `fig.show()`. For many figures, you would have `fig1,ax1`, you get the idea – gg349 Mar 10 '16 at 18:28

2 Answers2

4

With the implicit style that the question uses (where the figure object is not saved in a variable, and where plotting commands apply to the current figure), you can easily make a previous figure the current figure:

plt.figure(1)

will thus reactivate figure 1. plt.savefig() can then be used, additional plots can be made in it, etc.

Furthermore, you can also give a name to your figure when you create it, and then refer to it:

plt.figure("growth", figsize=…)
…
plt.figure("counts", figsize=…)
…
plt.figure("growth")  # This figure becomes the active one again

(the figure reference parameter is called num, but it doesn't have to be a number and can be a string, which makes for a clearer code).

Eric O. Lebigot
  • 91,433
  • 48
  • 218
  • 260
3

Things might make more sense if you start to use the object-oriented interface to matplotlib. In that case, you could do something like:

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(8, 6))
ax1 = fig.add_subplot(211)
ax1.scatter(x1, y1, c = 'r', alpha = 0.3)

ax2 = fig.add_subplot(212)
ax2.scatter(x2, y2, c = 'k', alpha = 0.7)

plt.show()

In this way, its easy to see that ax1 and ax2 belong to the figure instance, fig. You can then later refer back to ax1 and ax2, to plot more data on them, or adjust the axis limits, or add labels, etc., etc.

You can also add another figure, with its own set of subplots:

fig2 = plt.figure(figsize=(8, 6))
ax3 = fig2.add_subplot(211)

and then you can save the given figures at any point, and know that you are always referring to the correct figure:

fig.savefig('figure1.png')
fig2.savefig('figure2.png')
tmdavison
  • 64,360
  • 12
  • 187
  • 165
  • 1
    i am a little confused as to the purpose of the final line: plt.show() in your example? the 2 subplots are shown whether or not i include that line – laszlopanaflex Mar 11 '16 at 02:26
  • 1
    Ah yes, because you have the `%pylab inline` line there, the `plt.show` line is not needed. If you were working in a non-interactive environment, that would be required to display the plots – tmdavison Mar 11 '16 at 06:43