How to compile multiple plots into a single plot in Python?

Viewed 1508

I'm currently trying to combine multiple plots into a single plot (with sub-plots). Please check out the following code:

import matplotlib.pyplot as plt

a = list(range(1,10))
b = list(map(lambda x: x**2, a))
c = list(map(lambda x: x**3, a))
d = list(map(lambda x: x+200, a))

plots = []

plt.plot(a, b)
plots.append(plt.gcf())
plt.close()

plt.plot(a, c)
plots.append(plt.gcf())
plt.close()

plt.plot(b, c)
plots.append(plt.gcf())
plt.close()

plt.plot(a, d)
plots.append(plt.gcf())
plt.close()

fig, ax = plt.subplots(len(plots))
for i,plot_obj in enumerate(plots, start=1):
    print(f"{i=}, {plot_obj=}")
    ax[i].set_figure(plot_obj)
    plot_obj.show()


plt.tight_layout()
plt.show()

# plt.savefig('temp.png')

The constraints I have are -

  1. The plots will be created earlier - I'm storing the figure objects in a list.
  2. These plots need to be accessed later on in the code and a single figure needs to be created with each of the plot as a sub-plot.

On running the above code, I'm encountering the error - RuntimeError: Can not put single artist in more than one figure while trying to set the figure of each sub-plot. The thought process is to set each sub-plots's figure with the saved figure object. Is there any way to accomplish this ?

Thanks!

2 Answers

This may not be the cleanest way to write it, but I guess it does what you want:

a = list(range(1,10))
b = list(map(lambda x: x**2, a))
c = list(map(lambda x: x**3, a))
d = list(map(lambda x: x+200, a))

plots = []

fig=plt.figure()
plt.plot(a, b)
plots.append(fig)
plt.close()

fig=plt.figure()
plt.plot(a, c)
plots.append(fig)
plt.close()

fig=plt.figure()
ax3= plt.plot(b, c)
plots.append(fig)
plt.close()

fig=plt.figure()
plt.plot(a, d)
plots.append(fig)
plt.close()

fig,axs =plt.subplots(2,2)
axs[0,0].plot(a,b)
axs[0,1].plot(a,c)
axs[1,0].plot(b,c)
axs[1,1].plot(a,d)
plt.tight_layout()

plt.savefig('temp.png')

If you save the individual plots to files, you can later use imshow() and imread() from the matplotlib.image library to piece them together into one plot:

import matplotlib.pyplot as plt
import matplotlib.image as mpimg

a = list(range(1,10))
b = list(map(lambda x: x**2, a))
c = list(map(lambda x: x**3, a))
d = list(map(lambda x: x+200, a))

def save_plot(x, y, name):
    fig, ax = plt.subplots()
    ax.plot(x, y)
    ax.figure.savefig(name)
    plt.close()
        
save_plot(a, b, 'plot1')
save_plot(a, c, 'plot2')
save_plot(b, c, 'plot3')
save_plot(a, d, 'plot4')

fig, axs = plt.subplots(2, 2)
for i, ax in enumerate(axs.flat):
    ax.set_axis_off()
    filename = 'plot' + str(i+1) + '.png'
    ax.imshow(mpimg.imread(filename))
plt.show()

You may want to look into the imshow() documentation to reduce the whitespace around each subplot.

Related