So to do this I would keep a list of axes and when I delete the contents of one I would swap it out with a full one. I think the example below solved the problem (or at least gives an idea of how to solve it):
import matplotlib.pyplot as plt
# this is just a helper class to keep things clean
class MyAxis(object):
def __init__(self,ax,fig):
# this flag tells me if there is a plot in these axes
self.empty = False
self.ax = ax
self.fig = fig
self.pos = self.ax.get_position()
def del_ax(self):
# delete the axes
self.empty = True
self.fig.delaxes(self.ax)
def swap(self,other):
# swap the positions of two axes
#
# THIS IS THE IMPORTANT BIT!
#
new_pos = other.ax.get_position()
self.ax.set_position(new_pos)
other.ax.set_position(self.pos)
self.pos = new_pos
def main():
# generate a figure and 10 subplots in a grid
fig, axes = plt.subplots(ncols=5,nrows=2)
# get these as a list of MyAxis objects
my_axes = [MyAxis(ax,fig) for ax in axes.ravel()]
for ax in my_axes:
# plot some random stuff
ax.ax.plot(range(10))
# delete a couple of axes
my_axes[0].del_ax()
my_axes[6].del_ax()
# count how many axes are dead
dead = sum([ax.empty for ax in my_axes])
# swap the dead plots for full plots in a row wise fashion
for kk in range(dead):
for ii,ax1 in enumerate(my_axes[kk:]):
if ax1.empty:
print ii,"dead"
for jj,ax2 in enumerate(my_axes[::-1][kk:]):
if not ax2.empty:
print "replace with",jj
ax1.swap(ax2)
break
break
plt.draw()
plt.show()
if __name__ == "__main__":
main()
The extremely ugly for loop construct is really just a placeholder to give an example of how the axes can be swapped.