【问题标题】:Create subclass of dataframe with multiple inheritance创建具有多重继承的数据框的子类
【发布时间】:2020-01-25 13:59:00
【问题描述】:

您好,我想对 pandas 数据框进行子类化,但数据框的子类也将继承自我自己的自定义类。我想这样做是因为我想创建多个子类数据框,以及其他将共享此基类的属性和方法的子类(不是数据框)。

开始我的基类是

class thing(object):
   def __init__(self, item_location, name):
      self.name = name
      self.file = item_location
      self.directory = os.path.join(*item_location.split(os.path.sep)[0:-1])
   @property
   def name(self):
       return self._name
   @name.setter
   def name(self,val):
       self._name = val

   @property
   def file(self):
       return self._file
   @file.setter
   def file(self,val):
       self._location = val

   @property
   def directory(self):
      return self._directory
   @directory.setter
   def directory(self,val):
      self._directory = val

现在我的子类之一将从熊猫和事物继承

class custom_dataframe(thing,pd.DataFrame):
   def __init__(self, *args, **kwargs):
      super(custom_dataframe,self).__init__(*args,**kwargs)

   @property
   def _constructor(self):
      return custom_dataframe

我只是尝试制作一个空白数据框,并且只给它命名文件位置

custom_dataframe('/foobar/foobar/foobar.html','name')

我得到一个错误

(我无法在未连接到互联网的计算机上发布整个堆栈跟踪)

File "<stdin>", line 1, in <module>
File "<path to file with classes>", line x, in __init__
  self.name = name
<a bunch of stuff going through pandas library>
File "<path to pandas generic.py>", line 4372, in __getattr__
  return object.__getattribute__(self,name)
RecursionError: maximum recursion depth exceeded while calling a Python object

我正在使用熊猫 0.23.4

编辑:

item_location.split(os.pathsep)[0:-1] 更改为*item_location.split(os.path.sep)[0:-1]

【问题讨论】:

  • 我已经读过,正如我所说,我不想将我的事物属性添加为 _metadata,因为除了我的数据框子类之外的其他子类也将具有相同的属性。我宁愿不必在多个地方更改内容。
  • not have to change stuff in multiple places - 组合应该可以工作 - 在简单的情况下它可能看起来过于庞大,但效果会随着复杂性的增加而降低。无论如何,在您的情况下,尽量避免使用简单的属性名称,如 namefile 等。

标签: python pandas dataframe


【解决方案1】:

您在评论部分I've read that 中声明。但是,你没有。这就是问题的根源。由于that 描述了对 pandas 数据框进行子类化的步骤,包括定义原始属性的方法。

考虑对您的代码进行以下修改。关键部分是_metadata。我从thing 类中删除了所有属性,因为它们增加了原始属性名称的数量——它们都必须添加到_metadata。我还添加了__repr__ 方法来修复另一个RecursionError。最后,我删除了directory 属性,因为它给了我TypeError

import pandas as pd

class thing(object):

    def __init__(self, item_location, name):
        self.name = name
        self.file = item_location

    def __repr__(self):
        return 'dummy_repr'

class custom_dataframe(thing, pd.DataFrame):

    _metadata = ['name', 'file', 'directory']

    def __init__(self, *args, **kwargs):
        super(custom_dataframe, self).__init__(*args, **kwargs)

    @property
    def _constructor(self):
        return custom_dataframe

if __name__ == '__main__':
    cd = custom_dataframe('/foobar/foobar/foobar.html', 'name')

编辑。有点增强的版本 - 实现很差。

import pandas as pd

class thing:

    _metadata = ['name', 'file']

    def __init__(self, item_location, name):
        self.name = name
        self.file = item_location

class custom_dataframe(thing, pd.DataFrame):

    def __init__(self, *args, **kwargs):
        item_location = kwargs.pop('item_location', None)
        name = kwargs.pop('name', None)
        thing.__init__(self, item_location, name)
        pd.DataFrame.__init__(self, *args, **kwargs)

    @property
    def _constructor(self):
        return custom_dataframe

if __name__ == '__main__':

    cd = custom_dataframe(
        {1: [1, 2, 3], 2: [1, 2, 3]},
        item_location='/foobar/foobar/foobar.html',
        name='name')

【讨论】:

  • 非常感谢您抽出宝贵时间,但这如何帮助我不必将我的属性/方法从事物添加到我的 custom_dataframe 元数据?也许我很密集,我对python很陌生。为了记录,我关注了这篇文章dev.to/pj_trainor/extending-the-pandas-dataframe-133l
  • @MathWannaBe456 由于您继承自thing,您可以将_metadatacustom_dataframe 移动到thing
  • 所以我想我的下一个问题是,如何处理 pd.DataFrame 的输入?就像我尝试cd = custom_dataframe('/foobar/foobar/foobar.html', 'name',data={'A':[1,2,3]}) 并得到TypeError: __init__() got an unexpected keyword argument 'data'
  • @MathWannaBe456 您的下一个问题是关于 Python 中的继承。不是那么容易的话题,尤其是当您有多个基类时。所以让它正确 - 学习它。长话短说,您应该将不同基类的参数分开,然后使用适当的参数集调用 __init__ 方法。
  • 我尝试将__init__custom_dataframe 更改为__init__(self,item_location,name,data=None,index=None,columns=None,copy=None,*args, **kwargs),但我不知道如何将哪些输入委托给基类的哪些init。
猜你喜欢
  • 1970-01-01
  • 2020-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-05
  • 1970-01-01
  • 2014-01-25
  • 1970-01-01
相关资源
最近更新 更多