เกิดข้อผิดพลาดในการคัดลอกออบเจ็กต์คอมโพสิตที่ประกอบด้วย pandas.DataFrame เป็นส่วนใหญ่

ฉันพยายามใช้ องค์ประกอบ กับ 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. หากด้วยเหตุผลบางประการ การใช้ _ เป็นชื่อของแอตทริบิวต์จำลอง โปรดแจ้งให้เราทราบด้วยเหตุผลบางประการ

person Lei    schedule 10.04.2015    source แหล่งที่มา
comment
ดูเอกสาร 0.16.1 ที่นี่   -  person Jeff    schedule 02.06.2015


คำตอบ (1)


วิธีมาตรฐานในการดำเนินการนี้คือการกำหนดคุณสมบัติ _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!

แม้ว่ามันจะเป็นหลามที่ถูกต้องสมบูรณ์ที่จะใช้ _ เช่น:

sum( _ ** 2 for _ in x)

โดยทั่วไปแล้วสิ่งนี้จะถูกขมวดคิ้ว (ใช้ i หรืออะไรบางอย่างแทน)

ใน ipython _ หมายถึงค่าที่ส่งคืนก่อนหน้า

person Andy Hayden    schedule 10.04.2015
comment
ขอบคุณมากสำหรับความช่วยเหลือของคุณ. แต่การทำ class Foo(pd.DataFrame) เรากำลังจัดคลาสย่อย pd.DataFrame นั่นคือการสืบทอดมากกว่าการเรียบเรียงใช่ไหม และคลาสย่อย pandas DataFrame อาจเกิดปัญหาบางอย่าง เช่น การสูญเสียแอตทริบิวต์ที่กำหนดเองหลังจากการทำให้เป็นอนุกรม (เช่น groups.google.com/forum/#!topic/pydata/9Qimqt4ekvQ) ใช่ไหม? นั่นคือเหตุผลหลักว่าทำไมฉันถึงพยายามจัดองค์ประกอบภาพ - person Lei; 10.04.2015
comment
@LeiHuang ฉันไม่เห็นว่ามันจะแก้ไขปัญหาการทำให้เป็นอนุกรมได้อย่างไร คลาสย่อย IMO และการกำหนดวิธีการที่คุณต้องการเก็บข้อมูลเมตาไว้ (ทำอย่างนั้นก่อน) จากนั้นการเรียก super จะเป็นทางออกที่ดีกว่าหรือไม่ - person Andy Hayden; 10.04.2015
comment
@LeiHuang เจ๋งมาก! ขอบคุณ! (มันแวววาวและใหม่) ฉันจะอัปเดตคำตอบนี้ตามนั้น - person Andy Hayden; 06.06.2015