[Matplotlib-users] Remove Axes, Rescale Others to Fill Figure

Chad Parker parker.charles at gmail.com
Wed May 5 10:02:48 EDT 2021


Hi Adrien-

This is exactly the effect I'm looking to achieve. Thank you.

The only problem is that it appears to be a solution for only the near term:
MatplotlibDeprecationWarning:
The change_geometry function was deprecated in Matplotlib 3.4 and will be
removed two minor releases later. Use set_subplotspec instead.
  ax.change_geometry(n_nonempty, 1, idx+1)
MatplotlibDeprecationWarning:
The update_params function was deprecated in Matplotlib 3.4 and will be
removed two minor releases later.
  ax.change_geometry(n_nonempty, 1, idx+1)
MatplotlibDeprecationWarning:
The figbox attribute was deprecated in Matplotlib 3.4 and will be removed
two minor releases later. Use get_subplotspec().get_position(self.figure)
instead.
  ax.change_geometry(n_nonempty, 1, idx+1)

These messages suggest that there must be a way to accomplish this with
subplotspecs. A little further digging and I came up with a very similar
alternative:

gs = gridspec.GridSpec(len(fig.axes), 1)
for i, ax in enumerate(ig.axes):
  ax.set_subplotspec(gs[i])

Thanks for your solution!
--Chad

On Wed, May 5, 2021 at 3:09 AM vincent.adrien at gmail.com <
vincent.adrien at gmail.com> wrote:

> Hi Chad,
>
> I am no expert on the topic, but I found the `ax.update_geometry` method
> that may allow to solve your problem. See at the end of the following
> example adapted from your own code.
>
> ```python
> import matplotlib.pyplot as plt
> from numpy.random import random
> plt.ion()
>
> # generate some data (only 2 channels/5 runs in this example)
> nc, nr, nd = 2, 5, 12
> data = {c: {r: [random() for x in range(nd)] for r in range(nr)} for c in
> range(nc)}
> data[0][3] = [] # whoops, no data here.
>
> # save the handles here
> figaxlist = []
> # for each channel
> for chan in data:
>   nplots = len(data[chan].keys())
>   # create a figure with many subplots
>   fig, axs = plt.subplots(nplots, sharex=True)
>   figaxlist.append((fig, axs))
>   for run, ax in zip(data[chan].keys(), axs):
>     # plot the data
>     ax.plot(data[chan][run], color=f"C{run}")
>
> fig, axs = figaxlist[0]
>
> # removes axes, but leaves hole.
> fig.delaxes(fig.axes[3])
>
> # update the axes geometry information
> n_nonempty = len(fig.axes)  # amount of non empty plots
> for idx, ax in enumerate(fig.axes):
>     ax.change_geometry(n_nonempty, 1, idx+1)  # assuming single column
> layout
> ```
>
> Hopefully this is more or less what you are looking for.
>
> Regards,
> Adrien
>
> Le 04/05/2021 à 23:41, Chad Parker a écrit :
> > All-
> >
> > I frequently find myself in a position where I am programmatically
> generating figures with many subplots. For example, I might have data from
> 8 channels for 10 experimental runs and want to compare the different runs
> for each channel, ending up with 8 different figures (a figure for each
> channel), each of which has 10 stacked subplots (a subplot for each run).
> >
> > I look at the data I've plotted, and discover that, whoops, channel 0
> had an error and didn't produce any data during run number 3, and now I
> have an empty axis in the middle of my figure. I'd like to be able to
> delete that empty axes and have the other axes grow to fill the now empty
> space.
> >
> > The Figure class provides the delaxes method, which removes the axes
> from the figure, but doesn't change the size of any of the other axes. So I
> still end up with a hole in my figure. I was hoping that tight_layout might
> take care of it, but it assumes the axes are still there.
> >
> > Is there an easy way to do this? Failing that, what's the hard way (I
> assume it exists)?
> >
> > Thank you,
> > --Chad
> >
> >
> > # generate some data (only 2 channels/5 runs in this example)
> > nc, nr, nd = 2, 5, 12
> > data = {c: {r: [random() for x in range(nd)] for r in range(nr)} for c
> in range(nc)}
> > data[0][3] = [] # whoops, no data here.
> >
> > # save the handles here
> > figaxlist = []
> > # for each channel
> > for chan in data:
> >   nplots = len(data[chan].keys())
> >   # create a figure with many subplots
> >   fig, axs = plt.subplots(nplots, sharex=True)
> >   figaxlist.append((fig, axs))
> >   for run, ax in zip(data[chan].keys(), axs):
> >     # plot the data
> >     ax.plot(data[chan][run])
> >
> > fig, axs = figaxlist[0]
> >
> > # removes axes, but leaves hole.
> > fig.delaxes(fig.axes[3])
> >
> > _______________________________________________
> > Matplotlib-users mailing list
> > Matplotlib-users at python.org
> > https://mail.python.org/mailman/listinfo/matplotlib-users
> >
>
> _______________________________________________
> Matplotlib-users mailing list
> Matplotlib-users at python.org
> https://mail.python.org/mailman/listinfo/matplotlib-users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.python.org/pipermail/matplotlib-users/attachments/20210505/8598ac89/attachment-0001.html>


More information about the Matplotlib-users mailing list