如何为熊猫添加新属性。DataFrame 派生类?

How can I add new attributes to a pandas.DataFrame derived class?

提问人:Antonio Amador 提问时间:6/12/2023 最后编辑:YnjxsjmhAntonio Amador 更新时间:6/13/2023 访问量:72

问:

我想创建一个派生自略有不同的类。我将把一些额外的数据存储在新属性中,最后调用 .pandas.DataFrame__init__()DataFrame.__init__()

from pandas import DataFrame

class DataFrameDerived(DataFrame):
    def __init__(self, *args, **kwargs):
        self.derived = True
        super().__init__(*args, **kwargs)

DataFrameDerived({'a':[1,2,3]})

此代码在创建新属性 () 时出现以下错误:self.derived = True

RecursionError:调用 Python 对象时超出了最大递归深度

Python pandas init 派生 类属性

评论


答:

0赞 juanpa.arrivillaga 6/12/2023 #1

这是可能的,但实现对扩展不是很开放。事实上,官方文档建议使用替代方案。的实现很复杂,涉及各种混合蛋白的多重继承,而且,它使用各种属性设置/获取钩子,如 和 ,以提供语法糖,如 using 和 to work without using the syntax。如果你看一下堆栈跟踪,你可以看到有些事情正在发生:pd.DataFrame__getattr____setattr__df.some_columndf.some_colum = whateverdf['some_column']__setattr__

RecursionError                            Traceback (most recent call last)
Cell In[1], line 8
      5         self.derived = True
      6         super().__init__(*args, **kwargs)
----> 8 DataFrameDerived({'a':[1,2,3]})

Cell In[1], line 5, in DataFrameDerived.__init__(self, *args, **kwargs)
      4 def __init__(self, *args, **kwargs):
----> 5     self.derived = True
      6     super().__init__(*args, **kwargs)

File ~/miniconda3/envs/py311/lib/python3.11/site-packages/pandas/core/generic.py:6014, in NDFrame.__setattr__(self, name, value)
   6012 else:
   6013     try:
-> 6014         existing = getattr(self, name)
   6015         if isinstance(existing, Index):
   6016             object.__setattr__(self, name, value)

File ~/miniconda3/envs/py311/lib/python3.11/site-packages/pandas/core/generic.py:5986, in NDFrame.__getattr__(self, name)
   5976 """
   5977 After regular attribute access, try looking up the name
   5978 This allows simpler access to columns for interactive use.
   5979 """
   5980 # Note: obj.x will always call obj.__getattribute__('x') prior to
   5981 # calling obj.__getattr__('x').
   5982 if (
   5983     name not in self._internal_names_set
   5984     and name not in self._metadata
   5985     and name not in self._accessors
-> 5986     and self._info_axis._can_hold_identifiers_and_holds_name(name)
   5987 ):
   5988     return self[name]
   5989 return object.__getattribute__(self, name)

知道了这一点,人们可能会盲目地使用来绕过这一点:object.__setattr__

In [1]: from pandas import DataFrame
   ...:
   ...: class DataFrameDerived(DataFrame):
   ...:     def __init__(self, *args, **kwargs):
   ...:         object.__setattr__(self, 'derived', True)
   ...:         super().__init__(*args, **kwargs)
   ...:
   ...: DataFrameDerived({'a':[1,2,3]})
Out[1]:
   a
0  1
1  2
2  3

但同样,在没有真正理解实现的情况下,你只是交叉手指并希望“它有效”。它可能。但正如链接文档中所述,您可能还需要重写“构造函数”方法,以便您的数据帧类型在使用 DataFrame 方法时将返回其自身类型的数据帧

另一种方法是注册其他访问器命名空间,而不是使用继承。如果适合您,这是一种更简单的扩展熊猫的方法。

如果不了解您到底要完成什么的更多细节,就很难提出最佳的前进方向。但是你绝对应该从阅读我在扩展 Pandas 上链接到的所有文档开始

评论

0赞 Antonio Amador 6/13/2023
谢谢!官方文档链接非常有用