【问题标题】:Pandas groupby, resample, etc for subclassed DataFrame用于子类 DataFrame 的 Pandas groupby、resample 等
【发布时间】:2019-09-04 22:51:38
【问题描述】:

注意:下面的线程提示了一个拉取请求,该请求最终被合并到v1.10。此问题现已解决。

我正在使用子类 DataFrame,以便我可以更方便地访问特定于我的用例的一些转换方法和元数据。大多数 DataFrame 操作都按预期工作,因为它们返回子类的实例,而不是 pandas.DataFrame 的实例。然而,像 DataFrame.groupbyDataFrame.resample 这样的聚合操作似乎把这搞砸了。

这是一个错误,还是在定义我的子类时遗漏了什么?

下面是一个最小的例子,在 pandas 0.25.1 上测试:

class MyDataFrame(pd.DataFrame):
    @property
    def _constructor(self):
        return MyDataFrame

dates = pd.date_range('2019', freq='D', periods=365)
my_df = MyDataFrame(range(len(dates)), index=dates)

assert isinstance(my_df, MyDataFrame)
# Success!

assert isinstance(my_df.diff(), MyDataFrame)
# Success!

assert isinstance(my_df.sample(10), MyDataFrame)
# Success!

assert isinstance(my_df[:10], MyDataFrame)
# Success!

assert isinstance(my_df.resample("D").sum(), MyDataFrame)
# AssertionError

assert isinstance(my_df.groupby(df.index.month).sum(), MyDataFrame)
# AssertionError

【问题讨论】:

  • 从文档中,GroupBy 返回一个 DataFrameGroupBy 或 SeriesGroupBy 对象。 Resample 返回一个 Resampler 对象
  • 对,所以,一种选择是也继承 DataFrameGroupBy,然后以某种方式告诉 pandas 在 MyDataFrame 实例上调用 groupby 时使用正确的构造函数?也许我可以在我的子类中覆盖 groupby,但是我需要对其他聚合方法(例如滚动、重新采样、扩展)执行相同的操作。看起来这个问题可能有一个正式的“预期”解决方案。

标签: python pandas dataframe subclassing


【解决方案1】:

我不知道它本身是否是一个“错误”,但我同意无论如何都应该改变它。如果您查看一些用于 groupby-type 对象的source code,您会看到很多硬编码的return DataFrame(...)return Series(...)

正如您正确指出的那样,Pandas 对象有三种方法可用于构造它们自己的新版本:

  • _construct()创建相同类型的对象
  • _construct_sliced() 从类似数据框的对象创建类似系列的对象
  • _construct_expanddim() 从类似系列的对象创建类似数据框的对象

这些可以用来代替core/groupby/generic.py 中的硬编码类型,这很容易做到,因为groupby 对象将起始NDFrame 存储为属性obj

可以在我的 fork 上找到实施了这些更改的分支:https://github.com/alkasm/pandas/tree/groupby-preserve-subclass

【讨论】:

  • 谢谢。确实似乎尚不支持此功能。进一步的证据是,非常先进地使用 DataFrame 子类化的 GeoPandas 具有相同的行为。关于。 “熊猫不可能知道如何制作兼容系列”这句话,我认为这不是不可逾越的。如果子类对象或类被传入DataFrameGroupBy,那么它可以使用_constructor_sliced(见here)方法来创建兼容的Series类型。
  • @grge 哇,这是一个不错的发现!如果是这种情况,一个可能成为 PR 的解决方案就是存储完成 groupby 操作的类型,并使用这些方法而不是硬编码它。我建议在pandas-dev 上打开一个问题。
  • 我在这里提出了一个问题:github.com/pandas-dev/pandas/issues/28330
  • @pandichef 在我处理提交之后烦人,我被要求重新调整我的测试,此时我的提交变得与分组事物的大重构非常不一致,之后我想不通了解如何在所有情况下轻松修复该行为(请参阅此处:github.com/pandas-dev/pandas/pull/28573#issuecomment-553862758)。您应该能够将数据框转换回您的子类类型,这似乎比陈旧的尝试贡献分叉更容易维护。
  • @pandichef 嗯,这确实增加了复杂性。当然,您仍然可以再次投射和添加属性,但这绝对是脆弱的。这不是讨论的好地方,尽管我很乐意多聊——给我发一封电子邮件(查看我的 Github)!我可能会尝试再次获得此 PR。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-10
  • 2018-07-17
  • 1970-01-01
  • 2018-10-19
  • 2016-08-03
  • 2014-08-08
  • 1970-01-01
相关资源
最近更新 更多