【问题标题】:call special function when DataFrame is called upon custom class在自定义类上调用 DataFrame 时调用特殊函数
【发布时间】:2018-09-05 23:29:54
【问题描述】:

我有以下课程:

class Result(UserDict):
    """Implements a especial version of dictionary, that will return the keys 
ordered in the initialized way"""
    def __init__(self, keys_order, items):
        super().__init__(self)
        self.__keys_order = keys_order
        self.data = items

    def __repr__(self):
        attributes = ["{}:{}".format(_stringify(k), _stringify(self.data[k])) for k in self.keys()]
        return "{}".format(", ".join(attributes))

    def keys(self):
        return [key for key in self.__keys_order]


class Results(UserList):
    """Implements a especial kind of list, that has a method to_df"""
    def to_df(self):
        return pd.DataFrame(self.data, columns=self.data[0].keys())

这样,当我打印Result 的实例时,它将以所需的方式(由keys_order 确定)显示它的键。此外,Results 类实现了to_df 方法,该方法返回一个熊猫DataFrame,其中的列按键排序。

例如,我知道如果我希望 len(results) 函数以特殊方式运行,我必须在其中实现 __len__ 方法,以类似的方式,是否可以实现特殊方法,所以当pd.DataFrame(results) 是在 results 实例上调用的,它会调用 to_df 方法吗?所以我有按键排序的列。

【问题讨论】:

  • 您能否提供一些使用您的类的示例代码以及您期望的输出类型?

标签: python-3.x pandas oop metaprogramming


【解决方案1】:

您可以让您的 Result 类不仅继承自 UserDict,还继承自 pd.DataFrame。然后你只需要定义你的类的 _data 属性是你希望类交给 pd.DataFrame() 的,即你想要构造的 pd.DataFrame。

class Result(UserDict, pd.DataFrame):
    """Implements a especial version of dictionary, that will return the keys 
ordered in the initialized way"""
    def __init__(self, keys_order, items):
        super().__init__(self)
        self.__keys_order = keys_order
        self.data = items
        self._data = pd.DataFrame(self.data, columns=self.data[0].keys())

当查看 pd.DataFrame 类的 source code 时,这一点变得很明显:

def __init__(self, data=None, index=None, columns=None, dtype=None,
             copy=False):
    if data is None:
        data = {}
    if dtype is not None:
        dtype = self._validate_dtype(dtype)

    if isinstance(data, DataFrame):
        data = data._data

在调用__init__ 方法时,这是您在使用pd.DataFrame(results) 时有效执行的操作,它将检查结果是否是DataFrame 的实例。如果是,那么它只会将数据设置为results._data。或者,您的结果类也可以从 dict 继承,在这种情况下,将在 __init__ 内调用 dict 构造函数:

    elif isinstance(data, dict):
        mgr = self._init_dict(data, index, columns, dtype=dtype)

这里是 self._init_dict 的摘录,在你的情况下会被调用:

        else:
            keys = list(data.keys())
            if not isinstance(data, OrderedDict):
                keys = _try_sort(keys)
            columns = data_names = Index(keys)
            arrays = [data[k] for k in keys]

所以你必须为你的类定义一个keys() 方法来返回键(你已经拥有),以及__getitem__,以便最后一行中的 data[k] 返回列 k 的值.

【讨论】:

  • 我尝试以这种方式实现它,但它不起作用:/。我无法创建一个子对象或 UserDict 和 DataFrame 或 UserList 或 DataFrame,它引发了我无法调试的不同错误。另一方面,我实际上并不希望它被初始化为 DataFrame,我希望它是一个字典列表,然后,当我通过 DataFrame 初始化程序传递它时,我希望它自动拥有某个特定的键订购。
  • 如答案中所述,您也可以尝试从 dict 继承。有时间我可以试试这个
猜你喜欢
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 2021-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多