【问题标题】:How to draw and save a subplot figure as a new class method in Python?如何在 Python 中绘制子图并将其保存为新的类方法?
【发布时间】:2017-12-05 22:42:30
【问题描述】:

我想在 Python (v2.7.12) 中创建一个单独的类,它将绘图保存到文件中(此处为“test.eps”)并使用用户给出的一些标签、标题等作为参数(*args 和**kwargs)。

背景故事是我必须为科学数据创建图表,我希望 Python 类简单且适合我的情况。

import matplotlib.pyplot as plt 

# class of figures for channel flow
# with one subfigure
class Homfig(plt.Figure):

    # *args: list of plot features for ax1.plot
    #     (xdata,ydata,str linetype,str label)
    # **kwargs: list of axes features for ax1.set_$(STH)
    #     possible keys:
    #     title,xlabel,ylabel,xlim,ylim,xscale,yscale

    def __init__(self,*args,**kwargs):

        self.arg_lst = []
        for key,value in kwargs.iteritems():
            setattr(self,key,value)
            self.arg_lst.append(key)
        i=0
        for value in args:
            setattr(self,'plot'+str(i),value)
            i=i+1
        print 'list of attributes set: ', self.__dict__.keys()


    def hdraw(self):
        fig2=plt.figure()
        ax1 = fig2.add_subplot(111)
        for key in self.arg_lst:
            setattr(ax1,'set_'+key,getattr(self,key))
            print getattr(ax1,'set_'+key)


        ax1.plot([0, 1, 2, 3, 4], [0, 1, 2, 3, 4], label="Test", color='g')
        leg = ax1.legend(loc=4)
        plt.savefig('test.eps')
        plt.clf()

ff = Homfig(title='very important title',xlabel="xxx",ylabel="yyy")
ff.hdraw()

方法“hdraw”应该绘制我的数据并将其保存到文件中。 该代码没有给出错误消息,但看不到绘图标题或轴标签的变化。给 ax1 赋予属性并绘制绘图。

您能帮我理解这个问题并找到解决方案吗?

我在控制台中运行脚本: python homfigs.py

输出是: 属性集列表:['title', 'ylabel', 'xlabel', 'arg_lst'] 年年 xxx 很重要的标题

【问题讨论】:

    标签: python matplotlib plot subplot


    【解决方案1】:

    问题:

    注意区别

    ax.set_title = "some title"
    

    ax.set_title("some title")
    

    第一个将类属性set_title 从方法更改为字符串。第二个使用类方法set_title,它设置轴的标题。

    使用setattr 相当于第一种情况。因此,您通过用字符串覆盖它来破坏有用的类方法。之后,您 (a) 不能再使用该方法 (b) 仍然没有设置标题(甚至不能再这样做,因为 (a))。

    解决办法:

    虽然我不相信您正在使用的类的结构,但一种方法是实际调用相应的方法

    for key in self.arg_lst:
        getattr(ax1,'set_'+key)(getattr(self,key))
    

    建议:

    如果可以的话,我建议不要将属性存储在 Figure 类的属性中。无论如何,似乎不需要子类Figure。相反,您可以将 args 和 kwargs 存储在类变量中;例如kwargs 已经是带有值的字典,可用作绘图的属性,因此self.arg_lst 甚至不需要存在。

    import matplotlib.pyplot as plt 
    
    # class of figures for channel flow
    # with one subfigure
    class Homfig():
    
        # *args: list of plot features for ax1.plot
        #     (xdata,ydata,str linetype,str label)
        # **kwargs: list of axes features for ax1.set_$(STH)
        #     possible keys:
        #     title,xlabel,ylabel,xlim,ylim,xscale,yscale
    
        def __init__(self,*args,**kwargs):
            self.args = args
            self.kwargs = kwargs
            self.fig = plt.figure()
            self.ax = self.fig.add_subplot(111)
    
            for key, val in self.kwargs.iteritems():
                getattr(self.ax,'set_'+key)(val)
    
        def hdraw(self):
            self.ax.plot([0, 1, 2, 3, 4], [0, 1, 2, 3, 4], label="Test", color='g')
            leg = self.ax.legend(loc=4)
    
        def save(self, name="text"):
            self.fig.savefig(name+'.eps')
    
    
    ff = Homfig(title='very important title',xlabel="xxx",ylabel="yyy")
    ff.hdraw()
    ff.save()
    plt.show()
    

    【讨论】:

    • 这很好用,但是有一个问题:当我用 self.fig = plt.figure() 创建一个图形时,我不必在某个地方关闭它吗? - “plt.close(图)”
    • 可以关闭它。如果您的数字少于十位数左右,则无需担心。一旦脚本停止运行,内存就会被释放。如果您有许多复杂的大图并遇到问题,您当然可以在显示下一个之前关闭它们。您可以在某个时候使用plt.close(ff.fig)ff.fig.close() 或干脆plt.close("all")
    猜你喜欢
    • 1970-01-01
    • 2015-06-21
    • 1970-01-01
    • 2014-04-17
    • 1970-01-01
    • 2021-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多