复制主要由pandas.DataFrame组成的复合对象时出错

时间:2015-04-10 19:08:56

标签: python pandas composition

我尝试使用pandas.DataFrame以下列方式使用组合,但是当我尝试复制对象时,它会给我错误。

import numpy as np
import pandas as pd
import copy


class Foo(object):
    """
    Foo is composed mostly of a pd.DataFrame, and behaves like it too. 
    """

    def __init__(self, df, attr_custom):
        self._ = df
        self.attr_custom = attr_custom

    # the following code allows Foo objects to behave like pd.DataFame,
    # and I want to keep this behavior.
    def __getattr__(self, attr):
        return getattr(self._, attr)


df = pd.DataFrame(np.random.randint(0,2,(3,2)), columns=['A','B'])
foo = Foo(df)
foo_cp = copy.deepcopy(foo)

我得到的错误:

---> 16 foo_cp = copy.deepcopy(foo)

/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.pyc in deepcopy(x, memo, _nil)
    188                             raise Error(
    189                                 "un(deep)copyable object of type %s" % cls)
--> 190                 y = _reconstruct(x, rv, 1, memo)
    191 
    192     memo[d] = y

/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/copy.pyc in _reconstruct(x, info, deep, memo)
    341                 slotstate = None
    342             if state is not None:
--> 343                 y.__dict__.update(state)
    344             if slotstate is not None:
    345                 for key, value in slotstate.iteritems():

TypeError: 'BlockManager' object is not iterable 

我的问题:

  1. 知道这里发生了什么吗?
  2. 什么是"推荐"使用pandas.DataFrame组合的方式?
  3. 如果由于某些原因使用_作为虚拟属性的名称是个坏主意,请告诉我。

1 个答案:

答案 0 :(得分:3)

执行此操作的标准方法是定义_constructor属性:

class Foo(pd.DataFrame):
    @property
    def _constructor(self):
        return Foo

然后大多数DataFrame方法应该工作,并返回一个Foo。

In [11]: df = pd.DataFrame([[1, 2], [3, 4]])

In [12]: foo = Foo(df)

In [13]: foo.copy()
Out[13]:
   0  1
0  1  2
1  3  4

In [14]: type(foo.copy())
Out[14]: __main__.Foo

包括copy.deepcopy:

In [15]: copy.deepcopy(foo)
Out[15]:
   0  1
0  1  2
1  3  4

In [16]: type(copy.deepcopy(foo))
Out[16]: __main__.Foo

除此之外:我不会将_用作变量/方法名称,它根本不具有描述性。您可以使用_为名称添加前缀,以表明它应该被视为"私有",但是给它一个(描述性的!)名称,例如_df

_经常在python中用来表示"丢弃这个变量",所以你可以写:

sum(1 for _ in x)  # this is basically the same as len!

虽然使用_例如:

是完全有效的python
sum( _ ** 2 for _ in x)

这通常是不赞成的(而是使用i或其他东西)。

在ipython中_表示先前返回的值。