61

I want to plot 5 data frames in a 2 by 3 setting (i.e. 2 rows and 3 columns). This is my code: However there is an extra empty plot in the 6th position (second row and third column) which I want to get rid of it. I am wondering how I could remove it so that I have three plots in the first row and two plots in the second row.

import matplotlib.pyplot as plt
fig, axes = plt.subplots(nrows=2, ncols=3)

fig.set_figheight(8)
fig.set_figwidth(15)



df[2].plot(kind='bar',ax=axes[0,0]); axes[0,0].set_title('2')

df[4].plot(kind='bar',ax=axes[0,1]); axes[0,1].set_title('4')

df[6].plot(kind='bar',ax=axes[0,2]); axes[0,2].set_title('6')

df[8].plot(kind='bar',ax=axes[1,0]); axes[1,0].set_title('8')

df[10].plot(kind='bar',ax=axes[1,1]); axes[1,1].set_title('10')

plt.setp(axes, xticks=np.arange(len(observations)), xticklabels=map(str,observations),
        yticks=[0,1])

fig.tight_layout()

Plots

6 Answers 6

102

Try this:

fig.delaxes(axes[1][2])

A much more flexible way to create subplots is the fig.add_axes() method. The parameters is a list of rect coordinates: fig.add_axes([x, y, xsize, ysize]). The values are relative to the canvas size, so an xsize of 0.5 means the subplot has half the width of the window.

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks. It worked. Do you know how to move the two plots to the center?
If you want a subplot layout other than a regular grid, it is usually easier to use the fig.add_axes() method. It takes the coordinates of a rectangle (as a list) and returns a single axes object. The coordinates are relative to the window size. Il put an example in my answer.
Using add_axes is neither a very good nor recommended way of producing subplots. Either plt.subplots or Gridspec would be the ways to go and delaxes or ax.axis("off") can be used to delete or hide the subplot.
Can you please explain why? I understand that in most cases plt.subplots is sufficient, and then it is the recommended way. But in situations like this or if you want overlapping subplots I think this is the way to go.
Hi Johannes, What if I have defined my axes this way: f, ((ax1, ax2), (ax3, ax4), (ax5, ax6), (ax7, ax8)) = plt.subplots(4, 2, sharex=True, sharey=True , figsize=(10,20)) and I don't need my ax8?
|
45

Alternatively, using axes method set_axis_off():

axes[1,2].set_axis_off()

4 Comments

I find this easier to implement than @Johannes suggestion when I don't know the number of rows/cols ahead of time
I can't seem to make this work with the very first row of plots, ie axes[0,2].set_axis_off(). It throws a IndexError: too many indices for array. The subplots are 1 row of 4 columns. Any pointers on how to implement this on the first row?
In your case, axes is no longer a 2-D grid, it is a 1-D array of subplot objects. So you need to set axes[2].set_axis_off().
'[p.set_axis_off() for p in [i for i in axes.flatten() if len(i.get_title()) < 1]] '
18

If you know which plot to remove, you can give the index and remove like this:

axes.flat[-1].set_visible(False) # to remove last plot

Comments

12

A lazier version of Johannes's answers is to remove any axes that haven't had data added to them. This avoids maintaining a specification of which axes to remove.

[fig.delaxes(ax) for ax in axes.flatten() if not ax.has_data()]

Comments

11

Turn off all axes, and turn them on one-by-one only when you're plotting on them. Then you don't need to know the index ahead of time, e.g.:

import matplotlib.pyplot as plt

columns = ["a", "b", "c", "d"]
fig, axes = plt.subplots(nrows=len(columns))

for ax in axes:
    ax.set_axis_off()

for c, ax in zip(columns, axes):
    if c == "d":
        print("I didn't actually need 'd'")
        continue

    ax.set_axis_on()
    ax.set_title(c)

plt.tight_layout()
plt.show()

enter image description here

3 Comments

+1 because it works best when I write a general plotting routine and don't know how many subplots there are going to be. All other answers were strictly correct w.r.t. the OP's question, but this is more generic.
-1 because it will not work if you add sharex=True in subplots call. Nether for other solutions like delaxes and set_axis_off.
I'm surprised to read it does not work with sharex=True because in my case it works even before I knew about the comment. Maybe it was fixed in the matplotlib version I use. (At the time of writing: 3.7.2 )
2

Previous solutions do not work with sharex=True. If you have that, please consider the solution below, it also deals with 2 dimensional subplot layout.

import matplotlib.pyplot as plt


columns = ["a", "b", "c", "d"]
fig, axes = plt.subplots(4,1, sharex=True)


plotted = {}
for c, ax in zip(columns, axes.ravel()):
    plotted[ax] = 0
    if c == "d":
        print("I didn't actually need 'd'")
        continue
    ax.plot([1,2,3,4,5,6,5,4,6,7])
    ax.set_title(c)
    plotted[ax] = 1

if axes.ndim == 2:
    for a, axs in enumerate(reversed(axes)):
        for b, ax in enumerate(reversed(axs)):
            if plotted[ax] == 0:
                # one can use get_lines(), get_images(), findobj() for the propose
                ax.set_axis_off()
                # now find the plot above
                axes[-2-a][-1-b].xaxis.set_tick_params(which='both', labelbottom=True)
            else:
                break # usually only the last few plots are empty, but delete this line if not the case
else:
    for i, ax in enumerate(reversed(axes)):
        if plotted[ax] == 0:
            ax.set_axis_off()
            axes[-2-i].xaxis.set_tick_params(which='both', labelbottom=True)
            # should also work with horizontal subplots
            # all modifications to the tick params should happen after this
        else:
            break

plt.show()

example run result

2 dimensional fig, axes = plot.subplots(2,2, sharex=True)

when using 2,2

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.