通过设置__class__重新分类Python DataFrame

时间:2015-01-29 21:11:04

标签: python pandas casting subclass copy-constructor

我正在尝试创建一个DataFrame的子类,它使用很少的属性和方法扩展它。除了默认构造函数之外,还有很少其他像下面的那个从SQL表初始化DataFrame然后添加一些属性(我简化它并留下一个虚拟只是为了演示问题)。所以一旦我得到了最初的df,我就通过df.__class__ = Cls语句将它“转换”给我的班级。这对我来说似乎有点受欢迎,但是在这个问题上阅读了很少的帖子(例如Reclassing an instance in Python)这是一个有效的方法,而且似乎大部分时间都在工作。但问题是当我使用父类的方法(在这种情况下为DataFrame.append)时返回对象的新实例:sdf2 = sdf1.append(item) - 生成的sdf2类是DataFrame而不是SubDataFrame,因此print('sdf2: ', sdf2.name)失败,因为'DataFrame'没有属性'name'...底线,天真尝试使用标准DataFrame方法,我的对象已损坏...我可以通过编写(虚拟)来解决它在我的子类中附加'方法,但在这种情况下我需要为许多方法执行它,如果我不能使用继承的方法在子类中没有任何意义(我可以将DataFrame定义为我的类的成员变量)。 我想应该有这种子分类的最佳实践,只是不知道它。非常感谢任何帮助。 谢谢!

阿迪

import pandas as pd
import pandas.io.sql as pdsql

class SubDataFrame(pd.DataFrame):

    @classmethod
    def create(Cls):

        # df = pdsql.read_sql(db_query, db_connection)
        d = {'one' : [1., 2., 3., 4.], 'two' : [4., 3., 2., 1.]}
        df = pd.DataFrame(d, index=['a', 'b', 'c', 'd'])
        df.__class__ = Cls
        df.name = 'Test Obj'
        return df


if __name__ == "__main__":

    sdf1 = SubDataFrame.create()
    print('sdf1: ', sdf1.__class__)   # prints sdf1:  <class '__main__.SubDataFrame'>"
    print('sdf1: ', sdf1.name)        # prints "sdf1:  Test Obj"

    item = sdf1.iloc[0].copy()
    sdf2 = sdf1.append(item)
    print('sdf2: ', sdf2.__class__)   # prints: "sdf2:  <class 'pandas.core.frame.DataFrame'>"
    print('sdf2: ', sdf2.name)  # exception: "AttributeError: 'DataFrame' object has no attribute 'name'"
    pass

尝试使用@BrenB建议的super()进行测试。我阅读了参考文献(关于未绑定的超类classmethod),但仍然无法使其工作......这些是我的测试:

import pandas as pd
import pandas.io.sql as pdsql

class SubDataFrame(pd.DataFrame):

    @classmethod
    def create_reset_class(Cls):

        d = {'one' : [1., 2., 3., 4.], 'two' : [4., 3., 2., 1.]}
        df = pd.DataFrame(d, index=['a', 'b', 'c', 'd'])
        df.__class__ = Cls
        df.name = 'Test Obj'
        return df

    @classmethod
    def create_using_super(Cls):

        d = {'one' : [1., 2., 3., 4.], 'two' : [4., 3., 2., 1.]}
        df = super(SubDataFrame, Cls).__init__(d, index=['a', 'b', 'c', 'd'])
        df.name = 'Test Obj'
        return df

    def __init__(self):

        d = {'one' : [1., 2., 3., 4.], 'two' : [4., 3., 2., 1.]}
        df = super(SubDataFrame, self).__init__(d, index=['a', 'b', 'c', 'd'])
        df.name = 'Test Obj'
        return df

if __name__ == "__main__":

    sdf3 = SubDataFrame.create_using_super()
    sdf4 = SubDataFrame()

    sdf1 = SubDataFrame.create_reset_class()
    print('sdf1: ', sdf1.__class__)
    print('sdf1: ', sdf1.name)

    item = sdf1.iloc[0].copy()
    sdf2 = sdf1.append(item)
    print('sdf2: ', sdf2.__class__)
    print('sdf2: ', sdf2.name)
    pass

请注意,对于我的SubDataFrame,我有一个默认的__init__构造函数,create()是我的(非默认)构造函数,它是一个类方法,而在其中我调用pandas.DataFrame()这是标准绑定构造函数,期望自己而不是Cls。所以我尝试了两个选项:

一个。 df = super(SubDataFrame, Cls).__init__(d, index=['a', 'b', 'c', 'd'])在文件“C:\ Python34 \ lib \ site-packages \ pandas \ core \ frame.py”中生成错误AttributeError,第208行:'dict'对象没有属性'_init_dict'

湾使用标准绑定构造函数__init__不会生成任何错误,但df将返回为None(来自df = super(SubDataFrame, self).__init__(d, index=['a', 'b', 'c', 'd'])

我是否错误地使用了super()?这是一只熊猫虫吗?还有其他想法吗? 谢谢!

0 个答案:

没有答案