2014-11-01 59 views
0

我想通过下面的代码方法链派生数据框类

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() 

继我已经覆盖的DataFrame构造HYRY的意见,但是我需要设置初始化一些属性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 

我试过用functoolspartial

@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 

这似乎不是很优雅

+3

要么重写'loc'返回一个'CustomFrame',或'转换它的返回值GET'。 – jonrsharpe 2014-11-01 13:45:46

+0

@jonrsharpe mmmh覆盖'DataFrame.loc'意味着覆盖每个我可能想要链接的返回值的方法。 – greole 2014-11-01 16:08:37

+0

呃...是的,否则你不会得到一个'CustomFrame'。我想你可以用'__getattribute__'做些事情。 – jonrsharpe 2014-11-01 16:09:54

回答

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或装饰,这里是装饰的例子:

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 
+0

有趣的是,这可以以某种方式扩展,以便我可以在创建的'CustomFrame'上传递/初始化属性? – greole 2014-11-02 08:14:12

+0

@greole,你可以添加一个例子吗? – HYRY 2014-11-02 11:48:19

+0

我更新了我的问题 – greole 2014-11-02 13:28:35