【问题标题】:How can plot Artists be reused (Line2D)?如何重用绘图艺术家(Line2D)?
【发布时间】:2012-05-16 23:42:46
【问题描述】:

.plot 中的情节线如何在后续情节中重复使用?

我想在 4 个轴上绘制图,每个轴上的前三个单独的图,最后一个轴上的所有 3 个图。 代码如下:

from numpy import *
from matplotlib.pyplot import *
fig=figure()
data=arange(0,10,0.01)
ax1=fig.add_subplot(2,2,1)
ax2=fig.add_subplot(2,2,2)
ax3=fig.add_subplot(2,2,3)
ax4=fig.add_subplot(2,2,4)

line1=ax1.plot(data,data)
line2=ax2.plot(data, data**2/10, ls='--', color='green')
line3=ax3.plot(data, np.sin(data), color='red')
#could I somehow use previous plots, instead recreating them all?
line4=ax4.plot(data,data)
line4=ax4.plot(data, data**2/10, ls='--', color='green')
line4=ax4.plot(data, np.sin(data), color='red')
show()

生成的图片是:

有没有办法先定义图,然后将它们添加到轴上,然后绘制它们?这是我想到的逻辑:

#this is just an example, implementation can be different
line1=plot(data, data)
line2=plot(data, data**2/10, ls='--', color='green')
line3=plot(data, np.sin(data), color='red')
line4=[line1, line2, line3]

现在在 ax1 上绘制 line1,在 ax2 上绘制 line2,在 ax3 上绘制 line3,在 ax4 上绘制 line4。

【问题讨论】:

    标签: python matplotlib seaborn


    【解决方案1】:
    • OP 中请求的实现不起作用,因为plt.plot 返回的Line2D 绘图Artist 无法重用。尝试这样做,将根据def set_figure(self, fig): 生成RuntimeError
      • OP 中的line1 与使用Line2D 方法直接创建的line1 不同,因为绘制的Artist 具有不同的属性。
      • 关于seabornmatplotlib 的API,像seaborn.lineplot 这样的轴级绘图返回axes
        • p = sns.lineplot(...) 然后 p.get_children() 获取 Artist 对象。
    • 可以直接创建绘图艺术家,使用matplotlib.lines.Line2D 等方法,并在多个绘图中重复使用。
    • 使用标准导入做法、子图更新了代码,而不是使用列表理解来获得副作用(python 反模式)。
    • python 3.8.11matplotlib 3.4.3 测试
    import numpy as np
    from copy import copy
    import matplotlib.pyplot as plt
    from matplotlib.lines import Line2D
    
    # crate the figure and subplots
    fig, axes = plt.subplots(2, 2)
    
    # flatten axes into 1-D for easy indexing and iteration
    axes = axes.ravel()
    
    # test data
    data=np.arange(0, 10, 0.01)
    
    # create test lines
    line1 = Line2D(data, data)
    line2 = Line2D(data, data**2/10, ls='--', color='green')
    line3 = Line2D(data, np.sin(data), color='red')
    lines = [line1, line2, line3]
    
    # add the copies of the lines to the first 3 subplots
    for ax, line in zip(axes[0:-1], lines):
        ax.add_line(copy(line))
    
    # add 3 lines to the 4th subplot
    for line in lines:
        axes[3].add_line(line)
        
    # autoscale all the subplots if needed
    for _a in axes:
        _a.autoscale()
    
    plt.show()
    

    原答案

    • 这是一种可能的解决方案。我不确定它是否非常漂亮,但至少它不需要重复代码。
    import numpy as np, copy
    import matplotlib.pyplot as plt, matplotlib.lines as ml
    
    fig=plt.figure(1)
    data=np.arange(0,10,0.01)
    ax1=fig.add_subplot(2,2,1)
    ax2=fig.add_subplot(2,2,2)
    ax3=fig.add_subplot(2,2,3)
    ax4=fig.add_subplot(2,2,4)
    
    #create the lines
    line1=ml.Line2D(data,data)
    line2=ml.Line2D(data,data**2/10,ls='--',color='green')
    line3=ml.Line2D(data,np.sin(data),color='red')
    #add the copies of the lines to the first 3 panels
    ax1.add_line(copy.copy(line1))
    ax2.add_line(copy.copy(line2))
    ax3.add_line(copy.copy(line3))
    
    [ax4.add_line(_l) for _l in [line1,line2,line3]] # add 3 lines to the 4th panel
    
    [_a.autoscale() for _a in [ax1,ax2,ax3,ax4]] # autoscale if needed
    plt.draw()
    

    【讨论】:

      【解决方案2】:

      this question 也有一个很好的例子来引用以前的轴:

      fix, ax = plt.subplots(2, 2)
      ax[0,1].plot(data, data**2 / 10, ls='--', color='g')
      

      还解释了如何在每个子图上插入标题:

      ax[0,1].set_title('Simple plot')
      

      ax 的维度取决于子图参数:如果它们只是水平或垂直平铺,则 ax 只需要一个索引。

      【讨论】:

        【解决方案3】:

        我在 jupyter 笔记本中有一个更简单的用例。鉴于您在某处存储了一个图形对象,您如何重新绘制它。 例如:

        单元格 1:

        f = plt.figure(figsize=(18, 6))
        f.suptitle("Hierarchical Clustring", fontsize=20)
        dendrogram(Z, color_threshold=cut_off,
                   truncate_mode='lastp',
                   p=20)
        

        单元格 2:

        #plot f again, the answer is really simple
        f
        plt.show()
        

        就是这样。这样做的好处是您可以将图形存储在对象中,然后在必要时使用它们。

        【讨论】:

          【解决方案4】:

          我认为您的用法很好,但是您可以像这样将所有x,y 数据对传递给plot(尽管它读起来很糟糕!):

          ax4.plot(data, data, data, data**2 / 10, data, np.sin(data))
          

          一个有趣的不同方法是这样的:

          graph_data = [(data, data), (data, data**2 / 10), (data, np.sin(data))]
          [ax4.plot(i,j) for i,j in graph_data]
          

          【讨论】:

          • 我经常做错事,我一定会越来越好。 :) 我赞成这两种解决方案,接受答案的选择是任意的。
          猜你喜欢
          • 1970-01-01
          • 2013-11-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-11
          • 1970-01-01
          相关资源
          最近更新 更多