Can we make plt.subplots easier for arbitrary numbers of axes?

When building small multiples plots (i.e. figures with > 1 rows and/or columns), I frequently find myself writing something like:

ncols = 3
nrows = int(np.ceil(len(my_list) / ncols))
ax_width, ax_height = 3, 2
fig, axes = plt.subplots(
    ncols=ncols,
    nrows=nrows,
    figsize=(ax_width * ncols, ax_height * nrows)
)

It seems I’m not alone–searching on github there are lots of results for e.g. “nrows = int(np.ceil(”:

Search Term Python # Jupyter #
“nrows = int(np.ceil(” 2,536 446
“ncols = int(np.ceil(” 1,090 123
“nrows = int(math.ceil(” 367 41
“ncols = int(math.ceil(” 190 10

What do people think about adding one or both of the following arguments to e.g. plt.subplots (which filter down to Figure and GridSpec in turn):

  1. naxes to handle the number of required axes
  2. axsize to determine the required figsize

I think (1) is more useful and probably easier to implement than (2); you could call e.g.:

fig, axes = plt.subplots(ncols=3, nrows=-1, naxes=10, axsize=(3, 2))

And subplots would do the hard work of working out the correct values of nrows and figsize from the passed arguments.

I put together a very simple gist here by way of example. (I was trying to plot all of scipy’s simple window functions.) If you use -1 or None as the flag for the row or column that needs computing, everything else is simple to implement in the case that the user doesn’t do anything unexpected; the biggest changes would probably be to error handling and documentation.

Obviously this isn’t something that is difficult to implement outside the package, but it seems that it might be done frequently enough that I nice interface for users could be worthwhile.

Cheers,
Matt

P.S. And how about a Figure.hide_unused_axes method so we don’t have to write:

from itertools import zip_longest
fig, axes = plt.subplots()
for data, ax in zip_longest(data_items, axes.flat):
    if data is None:
        ax.set_visible(False)
    else:
        # amazing plotting code
2 Likes

I also think both your suggestions would be rad. Have you considered opening a feature request on github? You can use this template: https://github.com/matplotlib/matplotlib/issues/new?labels=New+feature&template=feature_request.md

Did you check out

If you want to implement something that takes the axes size (in inches?) and then determines an appropriate figure size, I’d suggest that is its own method, versus having conflicting kwargs in subplots