某些操作不考虑Series子类中的自定义属性

2024-10-03 02:33:55 发布

您现在位置:Python中文网/ 问答频道 /正文

根据https://pandas.pydata.org/pandas-docs/stable/internals.html
我应该可以给一个熊猫系列做分镜头

我的MCVE

from pandas import Series


class Xseries(Series):
    _metadata = ['attr']

    @property
    def _constructor(self):
        return Xseries

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

s = Xseries([1, 2, 3], attr=3)

请注意,attr属性是:

s.attr

3

但是,当我乘以2

(s * 2).attr

0

这是默认值。因此,没有传递attr。你可能会问,也许那不是你想要的行为?我认为这是根据文档https://pandas.pydata.org/pandas-docs/stable/internals.html#define-original-properties

如果我们使用mul方法,它似乎是有效的

s.mul(2).attr

3

但事实并非如此(与s * 2相同)

s.__mul__(2).attr

0

在我在github上创建一个问题之前,我想通过这个。这是虫子吗?你知道吗

有解决办法吗?你知道吗

我需要能够执行s * 2,并将attr属性传递给结果。你知道吗


Tags: httpsorgselfdocspandasdefhtmlkwargs
2条回答

如果@chrisb发布了一个类似的答案,我将删除这个答案。你知道吗


正如@chrisbhere发布的,这是一个开放的问题。你知道吗

Matthiasha发布了一个workaround,下面使用我的问题示例重新创建了这个workaround。你知道吗

from pandas import Series


class Xseries(Series):
    _metadata = ['attr']

    @property
    def _constructor(self):
        def _c(*args, **kwargs):
            # workaround for https://github.com/pandas-dev/pandas/issues/13208
            return Xseries(*args, **kwargs).__finalize__(self)
        return _c

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

现在问题解决了:

(Xseries([1, 2, 3], attr=3) * 2).attr

3

如果使用inspect.getsourcelines检查这两个函数mul__mul__的源代码,您会发现它们实际上有不同的实现。你知道吗

而且使用s.mul(2).attr仍然不起作用,因为它只是使用__finalize__来传播所有属性,而不是真正地将属性相乘。你知道吗

或者我误解了你的问题,你只是想传播而不是乘attr?你知道吗

如果是,您可以修改您的自定义__mul__函数来调用__finalize__。你知道吗

from pandas import Series


class Xseries(Series):
    _metadata = ['attr']

    @property
    def _constructor(self):
        return Xseries

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

    def __mul__(self, other):
        internal_result = super().__mul__(other)
        return internal_result.__finalize__(self)

s = Xseries([1, 2, 3], attr=3)

否则,可以手动将attr相乘并返回。你知道吗

from pandas import Series


class Xseries(Series):
    _metadata = ['attr']

    @property
    def _constructor(self):
        return Xseries

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

    def __mul__(self, other):
        internal_result = super().__mul__(other)
        if hasattr(other, "attr"):
            internal_result.attr = self.attr * other.attr
        else:
            internal_result.attr = self.attr * other
        return internal_result

s = Xseries([1, 2, 3], attr=3)

相关问题 更多 >