2014-11-01 60 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