matplotlib 复制轴内容并在新图形中显示

ergxz8rk  于 2023-04-07  发布在  其他
关注(0)|答案(2)|浏览(117)

假设我有这个代码:

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的轴,并提请它单独在一个新的数字
我试过做这样的事

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几乎没有任何有用的结果
编辑:
我不介意重新绘制所选的轴,但我不确定如何判断选择了哪个轴,因此,如果该信息以某种方式可用,那么它对我来说是有效的解决方案
编辑#2:
所以我设法做了这样的事情:

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,等等…),但我觉得一定有一个更好的方法来做到这一点

w41d8nur

w41d8nur1#

复制坐标轴

  • 这里的初始答案不起作用,我们将其保留以供将来参考,并了解为什么需要更复杂的方法。
#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。下面的方法可以工作。它pickle完整的图形并删除所有轴,只显示一个轴。

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()

重新创建图

当然,上述方法的另一种方法是每次单击坐标轴时在新的图形中重新创建绘图。为此,可以使用一个函数在指定的坐标轴上创建一个绘图,并将指定的索引作为输入。在图形创建过程中使用此函数,以及稍后在另一个图形中复制绘图,确保在所有情况下都有相同的绘图。

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()
rkkpypqq

rkkpypqq2#

例如,如果你有一个由函数plot_something生成的三条线的图,你可以这样做:

fig, axs = plot_something()
ax = axs[2]
l = list(ax.get_lines())[0]
l2 = list(ax.get_lines())[1]
l3 = list(ax.get_lines())[2]
plot(l.get_data()[0], l.get_data()[1])
plot(l2.get_data()[0], l2.get_data()[1])
plot(l3.get_data()[0], l3.get_data()[1])
ylim(0,1)

相关问题