Python 如何在不中断DataFrame.append()的情况下对DataFrame进行子类化或扩展?
我有一个复杂的对象,我想围绕熊猫数据帧构建。我曾尝试用一个子类来实现这一点,但在数据框中添加会重新初始化新实例中的所有属性,即使在使用Python 如何在不中断DataFrame.append()的情况下对DataFrame进行子类化或扩展?,python,python-3.x,pandas,Python,Python 3.x,Pandas,我有一个复杂的对象,我想围绕熊猫数据帧构建。我曾尝试用一个子类来实现这一点,但在数据框中添加会重新初始化新实例中的所有属性,即使在使用\u metadata时也是如此。我知道不建议对pandas对象进行子类化,但我不知道如何使用composition(或任何其他方法)实现我想要的功能,因此如果有人能告诉我如何在不进行子类化的情况下实现这一点,那将是非常棒的 我正在使用以下代码: import pandas as pd class thisDF(pd.DataFrame): @prop
\u metadata
时也是如此。我知道不建议对pandas对象进行子类化,但我不知道如何使用composition(或任何其他方法)实现我想要的功能,因此如果有人能告诉我如何在不进行子类化的情况下实现这一点,那将是非常棒的
我正在使用以下代码:
import pandas as pd
class thisDF(pd.DataFrame):
@property
def _constructor(self):
return thisDF
_metadata = ['new_property']
def __init__(self, data=None, index=None, columns=None, copy=False, new_property='reset'):
super(thisDF, self).__init__(data=data, index=index, columns=columns, dtype='str', copy=copy)
self.new_property = new_property
cols = ['A', 'B', 'C']
new_property = cols[:2]
tdf = thisDF(columns=cols, new_property=new_property)
正如我在上面链接的示例中所示,像tdf[['A','B']]这样的操作。新的_属性
可以很好地工作。但是,以创建新副本的方式修改数据会初始化不保留new\u属性的新实例。那么代码呢
print(tdf.new_property)
tdf = tdf.append(pd.Series(['a', 'b', 'c'], index=tdf.columns), ignore_index=True)
print(tdf.new_property)
输出
['A', 'B']
reset
如何扩展pd.DataFrame
,以便thisDF.append()
保留实例属性(如果不使用子类,则保留一些等效的数据结构)?请注意,我可以通过创建一个以DataFrame作为属性的类来完成我想要的一切,但我不想对所有DataFrame操作执行my_object.DataFrame.some_method()
。“[…]或使用我的_object class方法包装所有DataFrame方法(因为我假设这将是一项大量工作,对吗?)
不,不需要做很多工作。实际上,您不必自己包装包装对象的每个函数。可以使用getattr将调用向下传递到包装对象,如下所示:
class WrappedDataFrame:
def __init__(self, df, new_property):
self._df = df
self.new_property = new_property
def __getattr__(self, attr):
if attr in self.__dict__:
return getattr(self, attr)
return getattr(self._df, attr)
def __getitem__(self, item):
return self._df[item]
def __setitem__(self, item, data):
self._df[item] = data
\uuuu getattr\uuuu
是一个dunder方法,每次调用该类实例的方法时都会调用该方法。在我的实现中,每次隐式调用\uuu getattr\uuu
时,它都会检查对象是否具有您正在调用的方法。如果是,则返回并执行该方法。否则,它将在包装对象的\uuu dict\uu
中查找该方法并返回该方法
所以这个类在很大程度上就像一个数据帧一样工作。现在,您可以实现您想要的不同行为方式,如示例中的append
您可以使append修改包装的数据帧对象
def append(self, *args, **kwargs):
self._df = self._df.append(*args, **kwargs)
或者,它返回WrappedDataFrame
类的一个新实例,当然它保留了您的所有功能
def append(self, *args, **kwargs):
return self.__class__(self._df.append(*args, **kwargs))
您希望您的复杂对象做什么,从而导致您对DataFrame进行子类化?我经常创建一个类,该类将dataframe作为属性,该类中的函数可能会操作dataframe。例如,my\u object.add\u stuff(x)
可能调用self.dataframe.append(x)
。该对象表示引用网络,其中包含书目的数据框、引用的源和目标的数据框,以及用于网络分析的NetworkX图。引用和图表是属性,但我想通过执行my_object.DataFrameMethod()
来操作参考书目,而不是执行my_object.bib.DataFrameMethod()
或使用my_object
类方法包装所有数据框方法(因为我假设这将是大量工作,对吗?).这看起来对我有用,谢谢!我尝试过这样做,但我没有正确处理get/set项。