GridSpec of multiple subplots "the figure containing the passed axes is being cleared" GridSpec of multiple subplots "the figure containing the passed axes is being cleared" pandas pandas

GridSpec of multiple subplots "the figure containing the passed axes is being cleared"


The solution is to place the matplotlib Axes objects returned by pd.DataFrame.hist() into a figure with the desired layout. Unfortunately, placing new Axes objects into an existing Figure is a bit involved.

GridSpec layout

Creating the layout you want is not too complicated using nested matplotlib.gridspec.GridSpecs (see here for an example). Something like this.

import matplotlib.gridspec as gsnum_outer_columns = 2num_outer_rows = 2num_inner_columns = 2num_inner_rows = 3outer_layout = gs.GridSpec(num_outer_rows, num_outer_columns)inner_layout = []for row_num in range(num_outer_rows):    inner_layout.append([])    for col_num in range(num_outer_columns):        inner_layout[row_num].append(            gs.GridSpecFromSubplotSpec(                num_inner_rows,                 num_inner_columns,                 outer_layout[row_num, col_num]            )        )

You can create subplots within this grid using ax = plt.subplot(inner_layout[outer_row_num][outer_col_num][inner_row_num, inner_col_num]) and store the properly positioned axs for later.

Copying Axes into an existing Figure

Your df.hist() calls will produce something like this:

In [1]: dframe.hist(column=x, by=y)Out[1]:array([[<matplotlib.axes._subplots.AxesSubplot object at 0x1189be160>,        <matplotlib.axes._subplots.AxesSubplot object at 0x118e3eb50>],       [<matplotlib.axes._subplots.AxesSubplot object at 0x118e74d60>,        <matplotlib.axes._subplots.AxesSubplot object at 0x118ea8340>],       [<matplotlib.axes._subplots.AxesSubplot object at 0x118e76d62>,        <matplotlib.axes._subplots.AxesSubplot object at 0x118ea9350>]],      dtype=object)

Now you just have to replace the ax objects positioned earlier using your inner_layout with the AxesSubplot objects returned above. Unfortunately there isn't a convenient ax.from_axes(other_ax) method to do this, so you'll have to copy the Axes returned by df.hist() over manually by following this answer.