根据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上创建一个问题之前把它传递给SO。这是一个错误吗?
有解决方法吗?
我需要能够执行s * 2
并将attr
属性传递给结果。
答案 0 :(得分:2)
如果您使用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)
答案 1 :(得分:0)
如果@chrisb发布了类似的答案,我会删除这个答案。
由@chrisb here发布,这是一个悬而未决的问题。
Matthiasha发布了一个workaround,使用我在问题中的示例在下面重新创建。{/ p>
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