Matplotlib:从多个子图中获取单个子图

9 投票
2 回答
5118 浏览
提问于 2025-04-17 11:06

我有一个应用程序,里面有一个图形,包含九个子图(3x3),我想让用户选择其中一个图表,然后打开一个小的wx Python应用程序,方便用户编辑和放大指定的子图。

我想知道是否可以获取所选子图的所有信息,比如坐标轴标签、坐标轴格式、线条、刻度大小、刻度标签等等,然后快速在wx应用程序的画布上绘制出来?

我现在的解决方案太繁琐了,因为我只是重新绘制用户选择的图。我在想类似这样的做法,但效果不太对。

#ax is a dictionary containing each instance of the axis sub-plot
selected_ax = ax[6]
wx_fig = plt.figure(**kwargs)
ax = wx_fig.add_subplots(111)
ax = selected_ax
plt.show()

有没有办法把getp(ax)获取的属性保存到一个变量中,然后用setp(ax)选择这个变量的属性来构建一个新的图表?我觉得这些数据应该可以访问,因为调用getp(ax)时打印得很快,但我连以下代码在有两个y轴的坐标轴上都无法运行:

label = ax1.yaxis.get_label()
ax2.yaxis.set_label(label)

我感觉这可能不太可能,但我还是想问问。

2 个回答

1

这里有一个示例,演示了如何使用一个类来存储用户选择的子图(坐标轴),也就是被放大后的坐标轴。通过这个存储的坐标轴,你可以获取到所有需要的信息。这个示例展示了如何放大和恢复子图(坐标轴)。你还可以在这个类里写其他方法,这些方法可以访问到你选择的坐标轴,以满足你的需求。

import matplotlib.pyplot as plt

class Demo(object):
    """ Demo class for interacting with matplotlib subplots """
    def __init__(self):
        """ Constructor for Demo """
        self.zoomed_axis = None
        self.orig_axis_pos = None

    def on_click(self, event):
        """ Zoom or restore the selected subplot (axis) """
        # Note: event_axis is the event in the *un-zoomed* figure
        event_axis = event.inaxes
        if event_axis is None: # Clicked outside of any subplot
            return
        if event.button == 1:  # Left mouse click in a subplot
            if not self.zoomed_axis:
                self.zoomed_axis = event_axis
                self.orig_axis_pos = event_axis.get_position()
                event_axis.set_position([0.1, 0.1, 0.85, 0.85])
                # Hide all other axes
                for axis in event.canvas.figure.axes:
                    if axis is not event_axis:
                        axis.set_visible(False)
            else:
                self.zoomed_axis.set_position(self.orig_axis_pos)
                # Restore all axes
                for axis in event.canvas.figure.axes:
                    axis.set_visible(True)
                self.zoomed_axis = None
                self.orig_axis_pos = None
        else:  # any other event in a subplot
            return
        event.canvas.draw()

    def run(self):
        """ Run the demo """
        fig, axes = plt.subplots(nrows=2, ncols=2)
        for axis, color in zip(axes.flat, ['r', 'g', 'b', 'c']):
            axis.plot(range(10), color=color)
        fig.canvas.mpl_connect('button_press_event', self.on_click)
        plt.show()

def main():
    """ Main driver """
    demo = Demo()
    demo.run()

if __name__ == "__main__":
    main()
4

很遗憾,在matplotlib中,复制一个坐标轴或者在多个坐标轴之间共享图形元素是比较困难的。(虽然不是完全不可能,但重新绘制图形会简单很多。)

不过,下面这种情况怎么样呢?

当你左键点击一个子图时,它会占据整个图形;而当你右键点击时,你就可以“缩小”来显示其他的子图……

import matplotlib.pyplot as plt

def main():
    fig, axes = plt.subplots(nrows=2, ncols=2)
    for ax, color in zip(axes.flat, ['r', 'g', 'b', 'c']):
        ax.plot(range(10), color=color)
    fig.canvas.mpl_connect('button_press_event', on_click)
    plt.show()

def on_click(event):
    """Enlarge or restore the selected axis."""
    ax = event.inaxes
    if ax is None:
        # Occurs when a region not in an axis is clicked...
        return
    if event.button == 1:
        # On left click, zoom the selected axes
        ax._orig_position = ax.get_position()
        ax.set_position([0.1, 0.1, 0.85, 0.85])
        for axis in event.canvas.figure.axes:
            # Hide all the other axes...
            if axis is not ax:
                axis.set_visible(False)
    elif event.button == 3:
        # On right click, restore the axes
        try:
            ax.set_position(ax._orig_position)
            for axis in event.canvas.figure.axes:
                axis.set_visible(True)
        except AttributeError:
            # If we haven't zoomed, ignore...
            pass
    else:
        # No need to re-draw the canvas if it's not a left or right click
        return
    event.canvas.draw()

main()

撰写回答