Can you copy only some subplots to a new figure?

耗尽温柔 提交于 2021-01-28 05:32:53

问题


Is there a way to copy an axis (subplot) to a new figure? This is straightforward in other languages, but I understand that not even a deep copy would work with python's matplotlib. E.g. if I have a figure with 6 subplots, how can I copy 2 of those subplots to a new figure, with all the settings? Labels, tickmarks, legend, grid, etc.

I have found this answer , which is actually 2 in 1: the first no longer works (deprecated syntax), while I couldn't get the second to work in my case.

I manage to recreate a new figure and to remove the subplots I don't want, but I am left with a 3x2 grid of subplots, in which 2 are drawn and 4 are empty. Any suggestions?

I have put together a toy example below; my charts are, of course, way more complex with way more settings.

Note I used seaborn but it should be irrelevant - I believe this is a matplotlib question and the answer is going to be the same regardless of whether seaborn is used.

UPDATE: Following the tips from @Earnest, I can change the geometry of the new figure so that it only has two subplots, doing:

axes.change_geometry(1,2,2)

What I don't know how to do is to move the subplots around. To recap:

  • I start with 6 subplots in a 3x2 grid.
  • I pickle to memory, then unpickle to a new figure.
  • In the new figure, I keep only subplots 1 and 2, i.e. those identified by [rows, columns] [0,1] and [1,0]; the other 4 subplots are now blank spaces.
  • I want a [1x2] grid layout; if I do axes.change_geometry(1,2,2) then I get that layout, but one of my two subplots disappears.

Any suggestions?

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib
    import seaborn as sns
    import pickle
    import io


    sns.set(style='darkgrid')

    n=int(100)
    x=np.arange(0,n)

    fig, ax = plt.subplots(3,2)

    for i,a in enumerate(ax.flatten() ):
        y= np.random.rand(n)
        sns.lineplot( x, y , ax =a )
        a.set_title('Chart # ' + str(i+1))
        a.set_xlabel('my x')
        a.set_ylabel('my y')

    fig2, ax2 = plt.subplots(1,2)

    buf = io.BytesIO()
    pickle.dump(fig, buf)
    buf.seek(0)

    fig2=pickle.load(buf)

    tokeep=[1,2]

    # note that i == 1correponds to a[0,1]
    for i,a in enumerate(fig2.axes):
        if not i in(tokeep):
            fig2.delaxes(a)
        else:
            axes=a

回答1:


This is really @Ernest's answer; he pointed me in the right direction. I am typing this here as an answer for future reference, in the hope it can be useful to others. Basically I had to use change_geometry after deleting the subplots I didn't need. I think ggplot in the R universe has a cleaner implementation, but, overall, this seems OK - not too cumbersome. I have commented the code below - hope it's clear enough:

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import pickle
import io

sns.set(style='darkgrid')

#create the subplots
n=int(100)
x=np.arange(0,n)
fig, ax = plt.subplots(3,2)

for i,a in enumerate(ax.flatten() ):
    y= np.random.rand(n)
    sns.lineplot( x, y , ax =a )
    a.set_title('Chart # ' + str(i+1))
    a.set_xlabel('my x')
    a.set_ylabel('my y')

# pickle the figure, then unpickle it to a new figure
buf = io.BytesIO()
pickle.dump(fig, buf)
buf.seek(0)
fig2=pickle.load(buf)

# sets which subplots to keep
# note that i == 1correponds to a[0,1]
tokeep=[1,2]
axestokeep=[]

for i,a in enumerate(fig2.axes):
    if not i in(tokeep):
        fig2.delaxes(a)
    else:
        axestokeep.extend([a])

axestokeep[0].change_geometry(1,2,1)
axestokeep[1].change_geometry(1,2,2)


来源:https://stackoverflow.com/questions/55419931/can-you-copy-only-some-subplots-to-a-new-figure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!