派生DataFrame类的方法链接

时间:2014-11-01 13:43:55

标签: python numpy pandas

我正在尝试通过以下代码扩展pandas DataFrame

class CustomFrame(DataFrame):
    def __init__(self):
        DataFrame.__init__(self,{"a":[1,2,3,4],"b":[5,6,7,8]})
    def get(self):
        return self.loc[1]
    def foo(self):
        return 2*self

现在我想链接方法调用,如:

>>> c=CustomFrame()
>>> c.get().foo()
'Series' object has no attribute 'foo'

显然.loc会返回一个对自定义foo方法一无所知的系列。有没有办法让这项工作?

修改:

理想情况下,我想做一些像

这样的事情
c.method_from_data_frame().method_from_custom_frame().another_method_from_data_frame()

按照HYRY的建议,我已经覆盖了DataFrame的构造函数,但是我需要在CustomFrame初始化时设置一些属性

class CustomFrame(DataFrame):
    def __init__(self, *args, **kw):
        super(CustomFrame, self).__init__(*args, **kw)
        self.c = kw.get('c',False)

    @property
    def _constructor(self):
        return CustomFrame

   >>> c=CustomFrame(c=5)
   >>> print c.c
   5
   >>> print c.get().c
   False

我尝试使用functools partial

    @property
    def _constructor(self):
        return partial(CustomFrame,c=5)

但我收到pandas.core.common.PandasError: DataFrame constructor not properly called!错误。另一种方法是将get更改为

    def get(self):
        ret =  self.loc[[1]] # CustomFrame with default .c
        ret.c = self.c
        return ret

看起来不是很优雅

1 个答案:

答案 0 :(得分:1)

您可以覆盖_constructor属性,这是一个示例,因为self.loc[1]返回一个系列对象,我将其更改为self.loc[[1]]

from pandas import DataFrame


class CustomFrame(DataFrame):
    def __init__(self, *args, **kw):
        super(CustomFrame, self).__init__(*args, **kw)

    @property
    def _constructor(self):
        return CustomFrame        

    def get(self):
        return self.loc[[1]]

    def foo(self):
        return 2*self

c=CustomFrame({"a":[1,2,3,4],"b":[5,6,7,8]})
print c.get().foo()

修改

我没有更好的想法来复制属性,也许你可以使用_metadata或Decorator,这是一个装饰器的例子:

def copy_attrs(func):
    def wrap_func(self, *args, **kw):
        res = func(self, *args, **kw)
        res.c = self.c
        return res
    return wrap_func

class CustomFrame(DataFrame):
    def __init__(self, *args, **kw):
        self.__dict__["c"] = kw.pop("c", None)    
        super(CustomFrame, self).__init__(*args, **kw)

    @property
    def _constructor(self):
        return CustomFrame

    @copy_attrs
    def get(self):
       return self.loc[:2]

df = CustomFrame({"a":[1,2,3,4],"b":[5,6,7,8]}, c=100)
print df.c, df.get().c