pyplot - 复制轴内容并将其显示在新图形中 [英] pyplot - copy an axes content and show it in a new figure

查看:36
本文介绍了pyplot - 复制轴内容并将其显示在新图形中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有这个代码:

num_rows = 10
num_cols = 1
fig, axs = plt.subplots(num_rows, num_cols, sharex=True)
for i in xrange(num_rows):
     ax = axs[i]
     ax.plot(np.arange(10), np.arange(10)**i)
plt.show()

结果图有太多信息,现在我想选择 1 个轴并在新图中单独绘制

the result figure has too much info and now I want to pick 1 of the axes and draw it alone in a new figure

我尝试做这样的事情

def on_click(event):
    axes = event.inaxes.get_axes()
    fig2 = plt.figure(15)
    fig2.axes.append(axes)
    fig2.show()

fig.canvas.mpl_connect('button_press_event', on_click)

但它并没有完全奏效.什么是正确的方法呢?搜索文档并抛出 SE 几乎没有任何有用的结果

but it didn't quite work. what would be the correct way to do it? searching through the docs and throw SE gave hardly any useful result

我不介意重新绘制选定的轴,但我不确定如何判断选择了哪个轴,所以如果该信息以某种方式可用,那么它对我来说是一个有效的解决方案

I don't mind redrawing the chosen axes, but I'm not sure how can I tell which of the axes was chosen so if that information is available somehow then it is a valid solution for me

编辑#2:

所以我设法做这样的事情:

so I've managed to do something like this:

def on_click(event):
    fig2 = plt.figure(15)
    fig2.clf()
    for line in event.inaxes.axes.get_lines():
         xydata = line.get_xydata()
         plt.plot(xydata[:, 0], xydata[:, 1])
    fig2.show()

这似乎是工作"(所有其他信息都丢失了 - 标签、线条颜色、线条样式、线条宽度、xlim、ylim 等...)但我觉得一定有更好的方法来做到这一点

which seems to be "working" (all the other information is lost - labels, lines colors, lines style, lines width, xlim, ylim, etc...) but I feel like there must be a nicer way to do it

谢谢

推荐答案

复制坐标轴

这里的初始答案不起作用,我们保留它以供将来参考,并了解为什么需要更复杂的方法.

#There are some pitfalls on the way with the initial approach. 
#Adding an `axes` to a figure can be done via `fig.add_axes(axes)`. However, at this point, 
#the axes' figure needs to be the figure the axes should be added to. 
#This may sound a bit like running in circles but we can actually set the axes' 
#figure as `axes.figure = fig2` and hence break out of this.

#One might then also position the axes in the new figure to take the usual dimensions. 
#For this a dummy axes can be added first, the axes can change its position to the position 
#of the dummy axes and then the dummy axes is removed again. In total, this would look as follows.

import matplotlib.pyplot as plt
import numpy as np

num_rows = 10
num_cols = 1
fig, axs = plt.subplots(num_rows, num_cols, sharex=True)
for i in xrange(num_rows):
     ax = axs[i]
     ax.plot(np.arange(10), np.arange(10)**i)
     
     
def on_click(event):
    axes = event.inaxes
    if not axes: return   
    fig2 = plt.figure()
    axes.figure=fig2
    fig2.axes.append(axes)
    fig2.add_axes(axes)
    
    dummy = fig2.add_subplot(111)
    axes.set_position(dummy.get_position())
    dummy.remove()
    fig2.show()

fig.canvas.mpl_connect('button_press_event', on_click)


plt.show()

#So far so good, however, be aware that now after a click the axes is somehow 
#residing in both figures, which can cause all sorts of problems, e.g. if you
# want to resize or save the initial figure.

相反,以下内容将起作用:

问题是无法复制轴(即使 deepcopy 也会失败).因此,要获得轴的真实副本,您可能需要使用 pickle.以下将起作用.它腌制了完整的图形并删除了除一个轴之外的所有要显示的轴.

The problem is that axes cannot be copied (even deepcopy will fail). Hence to obtain a true copy of an axes, you may need to use pickle. The following will work. It pickles the complete figure and removes all but the one axes to show.

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

num_rows = 10
num_cols = 1
fig, axs = plt.subplots(num_rows, num_cols, sharex=True)
for i in range(num_rows):
     ax = axs[i]
     ax.plot(np.arange(10), np.arange(10)**i)

def on_click(event):

    if not event.inaxes: return
    inx = list(fig.axes).index(event.inaxes)
    buf = io.BytesIO()
    pickle.dump(fig, buf)
    buf.seek(0)
    fig2 = pickle.load(buf) 

    for i, ax in enumerate(fig2.axes):
        if i != inx:
            fig2.delaxes(ax)
        else:
            axes=ax

    axes.change_geometry(1,1,1)
    fig2.show()

fig.canvas.mpl_connect('button_press_event', on_click)

plt.show()

重新创建绘图

上述替代方案当然是每次单击轴时在新图形中重新创建绘图.为此,可以使用一个函数,该函数在指定的轴上创建一个绘图,并使用指定的索引作为输入.在图形创建期间以及稍后在另一个图形中复制图形时使用此函数可确保在所有情况下都具有相同的图形.

Recreate plots

The alternative to the above is of course to recreate the plot in a new figure each time the axes is clicked. To this end one may use a function that creates a plot on a specified axes and with a specified index as input. Using this function during figure creation as well as later for replicating the plot in another figure ensures to have the same plot in all cases.

import matplotlib.pyplot as plt
import numpy as np

num_rows = 10
num_cols = 1
colors = plt.rcParams["axes.prop_cycle"].by_key()["color"]
labels = ["Label {}".format(i+1) for i in range(num_rows)]

def myplot(i, ax):
    ax.plot(np.arange(10), np.arange(10)**i, color=colors[i])
    ax.set_ylabel(labels[i])


fig, axs = plt.subplots(num_rows, num_cols, sharex=True)
for i in xrange(num_rows):
     myplot(i, axs[i])


def on_click(event):
    axes = event.inaxes
    if not axes: return
    inx = list(fig.axes).index(axes)
    fig2 = plt.figure()
    ax = fig2.add_subplot(111)
    myplot(inx, ax)
    fig2.show()

fig.canvas.mpl_connect('button_press_event', on_click)

plt.show()

这篇关于pyplot - 复制轴内容并将其显示在新图形中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆