2017-07-28 34 views
4

我想從熊貓DataFrame建立一個類。我只想爲DataFrame類添加一個屬性'name'。但下面的代碼在達到遞歸最大深度時產生錯誤。使其工作的方式是什麼?由於建立一個現有的類

import pandas as pd 
class DatFrame(pd.DataFrame): 
    def __init__(self, name, data=None, index=None, columns=None, 
       dtype=None, copy=False): 
     self.name = name 
     pd.DataFrame.__init__(self, data=None, index=None, 
           columns=None, dtype=None, copy=False) 


x = array([[9, 7, 5], 
      [7, 3, 1], 
      [8, 8, 3], 
      [7, 4, 3]]) 
cols = ['a', 'b', 'c'] 
index = ['D', 'E', 'F', 'G'] 

s = DatFrame('huy', x, index, cols) 

錯誤:RecursionError:當調用一個Python對象

+5

只要你知道,你可以動態將屬性添加到Python對象。所以,假設你有一個由變量'df'引用的'pd.DataFrame',那麼你可以做'df.name ='huy'' –

+0

而且,在對'pandas'數據結構進行子類化時還有特殊的考慮。請參閱[文檔](http://pandas.pydata.org/pandas-docs/stable/internals.html#subclassing-pandas-data-structures) –

回答

5

首先,你傳遞None你的數據幀

其次,它是調用修復的所有參數最大遞歸深度超過先設定__init__方法,然後設定name

這可能是因爲pd.DataFrame對象初始化時(在__getattr__發生遞歸)預計空可變字典,你name成員混淆它:

class DatFrame(pd.DataFrame): 
    def __init__(self, name, data=None, index=None, columns=None, 
       dtype=None, copy=False): 
     pd.DataFrame.__init__(self, data=data, index=index, 
           columns=columns, dtype=dtype, copy=copy) 
     self.name = name 

作爲一般規則,它總是更好地調用父構造函數的第一件事,然後設置你的具體情況。

正如評論所說,如果這只是增加name(不添加方法),你可以創建一個工廠方法是動態地添加屬性,無需繼承:

def create_datframe(name,*args,**kwargs): 
    r = pd.DataFrame(*args,**kwargs) 
    r.name = name 
    return r 
+2

是的,雖然我可以看到子類化的優點,當你想添加屬性,在這種情況下,因爲子類化「pd.Dataframe」是非平凡的,我可能只是去動態屬性。當然,在查看遞歸錯誤的堆棧軌跡時,會發現屬性和名稱會有一些變化,這很有意義,因爲您可以通過名稱作爲數據框中的屬性來訪問列。有一個非空的'__dict__'肯定會搞亂任何複雜的初始化。 –

+0

@ juanpa.arrivillaga AFAIK子類添加屬性或動態添加屬性具有相同的效果。類__dict__被更新(外部或'__init__'內),所以它不會改變一件事情,除非它最初被構建。 –