Search code examples
pythonmatplotlibsubplot

Can I create AxesSubplot objects, then add them to a Figure instance?


Looking at the matplotlib documentation, it seems the standard way to add an AxesSubplot to a Figure is to use Figure.add_subplot:

from matplotlib import pyplot

fig = pyplot.figure()
ax = fig.add_subplot(1,1,1)
ax.hist( some params .... )

I would like to be able to create AxesSubPlot-like objects independently of the figure, so I can use them in different figures. Something like

fig = pyplot.figure()
histoA = some_axes_subplot_maker.hist( some params ..... )
histoA = some_axes_subplot_maker.hist( some other params ..... )
# make one figure with both plots
fig.add_subaxes(histo1, 211)
fig.add_subaxes(histo1, 212)
fig2 = pyplot.figure()
# make a figure with the first plot only
fig2.add_subaxes(histo1, 111)

Is this possible in matplotlib and if so, how can I do this?

Update: I have not managed to decouple creation of Axes and Figures, but following examples in the answers below, can easily re-use previously created axes in new or olf Figure instances. This can be illustrated with a simple function:

def plot_axes(ax, fig=None, geometry=(1,1,1)):
    if fig is None:
        fig = plt.figure()
    if ax.get_geometry() != geometry :
        ax.change_geometry(*geometry)
    ax = fig.axes.append(ax)
    return fig

Solution

  • Typically, you just pass the axes instance to a function.

    For example:

    import matplotlib.pyplot as plt
    import numpy as np
    
    def main():
        x = np.linspace(0, 6 * np.pi, 100)
    
        fig1, (ax1, ax2) = plt.subplots(nrows=2)
        plot(x, np.sin(x), ax1)
        plot(x, np.random.random(100), ax2)
    
        fig2 = plt.figure()
        plot(x, np.cos(x))
    
        plt.show()
    
    def plot(x, y, ax=None):
        if ax is None:
            ax = plt.gca()
        line, = ax.plot(x, y, 'go')
        ax.set_ylabel('Yabba dabba do!')
        return line
    
    if __name__ == '__main__':
        main()
    

    To respond to your question, you could always do something like this:

    def subplot(data, fig=None, index=111):
        if fig is None:
            fig = plt.figure()
        ax = fig.add_subplot(index)
        ax.plot(data)
    

    Also, you can simply add an axes instance to another figure:

    import matplotlib.pyplot as plt
    
    fig1, ax = plt.subplots()
    ax.plot(range(10))
    
    fig2 = plt.figure()
    fig2.axes.append(ax)
    
    plt.show()
    

    Resizing it to match other subplot "shapes" is also possible, but it's going to quickly become more trouble than it's worth. The approach of just passing around a figure or axes instance (or list of instances) is much simpler for complex cases, in my experience...