我正在尝试通过以下代码扩展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
看起来不是很优雅
答案 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