在不改变原始对象的情况下对DataFrame进行子类化

问题描述 投票:1回答:1

正如mentioned a while back by @piRSquared,以文档中建议的方式或通过geopandas' GeoDataFrame对pandas DataFrame进行子类化,开启了原始对象不必要的变异的可能性:

class SubFrame(pd.DataFrame):

    def __init__(self, *args, **kwargs):
        attr = kwargs.pop('attr', None)
        super(SubFrame, self).__init__(*args, **kwargs)
        self.attr = attr

    @property
    def _constructor(self):
        return SubFrame

    def somefunc(self):
        """Add some extended functionality."""
        pass

df = pd.DataFrame([[1, 2], [3, 4]])
sf = SubFrame(df, attr=1)

sf[:] = np.nan  # Modifies `df`
print(df)

#     0   1
# 0 NaN NaN
# 1 NaN NaN

容易出错的“修复”是在实例化时传递一个副本:

sf = SubFrame(df.copy(), attr=1)

但这很容易受到用户错误的影响。我的问题是:我可以在self本身内创建class SubFrame(传递的DataFrame)的副本吗?我该怎么做呢?

如果答案是“不”,我也很欣赏,所以我可以在浪费时间之前废弃这项努力。


A polite request

大熊猫文档suggest two alternatives

  1. 使用pipe的可扩展方法链
  2. 组成

我已经彻底考虑了这两个问题,所以如果答案可以避免一般性的讨论,为什么这两个选择更好/更安全,我会很感激。

python python-3.x pandas inheritance
1个回答
1
投票

Self不是您传递的数据帧。无论如何,您可以在init函数中执行复制。

例如

import copy

def __init__(self, farg, **kwargs):
    farg = copy.deepcopy(farg)
    attr = kwargs.pop('attr', None)
    super().__init__(farg)
    self.attr = attr

应该告诉你,farg是你传递的df。

我对子类化DataFrame知之甚少,所以如果你想保留原始的init结构,你可以复制所有的* args。不能说这种方法的安全性。

def __init__(self, *args, **kwargs):
    cargs = tuple(copy.deepcopy(arg) for arg in args)
    attr = kwargs.pop('attr', None)
    super().__init__(*cargs, **kwargs)
    self.attr = attr
© www.soinside.com 2019 - 2024. All rights reserved.