Python:将系列子类存储为DataFrame列

Python:将系列子类存储为DataFrame列,python,pandas,Python,Pandas,我想创建一个DataFrame,它包含我定义的许多不同的Series子类。然而,当分配给数据帧时,子类似乎从系列中剥离出来 下面是一个玩具示例来说明问题: >>> import pandas as pd >>> class SeriesSubclass(pd.Series): ... @property ... def _constructor(self): ... return SeriesSubclass ... d

我想创建一个
DataFrame
,它包含我定义的许多不同的
Series
子类。然而,当分配给
数据帧
时,子类似乎从
系列
中剥离出来

下面是一个玩具示例来说明问题:

>>> import pandas as pd
>>> class SeriesSubclass(pd.Series):
...     @property
...     def _constructor(self):
...         return SeriesSubclass
...     def times_two(self):
...     """Method I need in this subclass."""
...         return self * 2
...
>>> subclass = SeriesSubclass([7, 8, 9])
>>> type(subclass)                   # fine
<class '__main__.SeriesSubclass'>
>>> subclass.times_two()             # fine
0    14
1    16
2    18
dtype: int64
>>>
>>> data = pd.DataFrame([[1, 2, 3], [4, 5, 6]], columns=list('ABC'))
>>> data['D'] = subclass
>>> type(data['D'])                  # not good
<class 'pandas.core.series.Series'>
>>> data['D'].times_two()            # not good
Traceback (most recent call last):
    ...
AttributeError: 'Series' object has no attribute 'times_two'
>>将熊猫作为pd导入
>>>类别系列子类别(pd系列):
...     @财产
...     def_构造函数(自身):
...         返回序列子类
...     def次_2(自):
...     “”“此子类中需要的方法。”“”
...         返回自我*2
...
>>>subclass=SeriesSubclass([7,8,9])
>>>类型(子类)#精细
>>>子类.times_two()#很好
0    14
1    16
2    18
数据类型:int64
>>>
>>>data=pd.DataFrame([[1,2,3],[4,5,6]],columns=list('ABC'))
>>>数据['D']=子类
>>>类型(数据['D'])#不好
>>>数据['D'].乘以2()#不好
回溯(最近一次呼叫最后一次):
...
AttributeError:“Series”对象没有属性“times\u two”

我已经看到这个问题以前可能已经被提出过,但我看不出实际的解决方案。作为一个如此庞大的库,很难遵循各种PRs、doc版本等,而且就我所知,子类化机制似乎没有得到很好的描述()

我认为你运气不好,除非你还定义了自己的
pd.DataFrame
子类。这将是一项更加艰巨的任务

以这个例子为例

df = pd.DataFrame()
s = pd.Series([1, 2, 3])
s.random_attribute = 'hello!'
print(s.random_attribute)

df['A'] = s
print(df.A.random_attribute)

hello!
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-273-e0031d933193> in <module>()
      5 
      6 df['A'] = s
----> 7 print(df.A.random_attribute)

//anaconda/envs/3.5/lib/python3.5/site-packages/pandas/core/generic.py in __getattr__(self, name)
   2742             if name in self._info_axis:
   2743                 return self[name]
-> 2744             return object.__getattribute__(self, name)
   2745 
   2746     def __setattr__(self, name, value):

AttributeError: 'Series' object has no attribute 'random_attribute'
df=pd.DataFrame()
s=pd.系列([1,2,3])
s、 随机_属性='hello!'
打印(s.random_属性)
df['A']=s
打印(df.A.random_属性)
你好
---------------------------------------------------------------------------
AttributeError回溯(最近一次呼叫上次)
在()
5.
6 df['A']=s
---->7打印(df.A.random_属性)
//anaconda/envs/3.5/lib/python3.5/site-packages/pandas/core/generic.py in_u____getattr____(self,name)
2742如果自身信息轴中的名称:
2743返回自我[姓名]
->2744返回对象。\uuuu getattribute\uuuuu(self,name)
2745
2746定义设置属性(自身、名称、值):
AttributeError:“Series”对象没有属性“random\u attribute”

df.A
不是
s
df.A
s
构造而来,忽略它是什么类型。

我认为你运气不好,除非你还定义了自己的
pd.DataFrame
子类。这将是一项更加艰巨的任务

以这个例子为例

df = pd.DataFrame()
s = pd.Series([1, 2, 3])
s.random_attribute = 'hello!'
print(s.random_attribute)

df['A'] = s
print(df.A.random_attribute)

hello!
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-273-e0031d933193> in <module>()
      5 
      6 df['A'] = s
----> 7 print(df.A.random_attribute)

//anaconda/envs/3.5/lib/python3.5/site-packages/pandas/core/generic.py in __getattr__(self, name)
   2742             if name in self._info_axis:
   2743                 return self[name]
-> 2744             return object.__getattribute__(self, name)
   2745 
   2746     def __setattr__(self, name, value):

AttributeError: 'Series' object has no attribute 'random_attribute'
df=pd.DataFrame()
s=pd.系列([1,2,3])
s、 随机_属性='hello!'
打印(s.random_属性)
df['A']=s
打印(df.A.random_属性)
你好
---------------------------------------------------------------------------
AttributeError回溯(最近一次呼叫上次)
在()
5.
6 df['A']=s
---->7打印(df.A.random_属性)
//anaconda/envs/3.5/lib/python3.5/site-packages/pandas/core/generic.py in_u____getattr____(self,name)
2742如果自身信息轴中的名称:
2743返回自我[姓名]
->2744返回对象。\uuuu getattribute\uuuuu(self,name)
2745
2746定义设置属性(自身、名称、值):
AttributeError:“Series”对象没有属性“random\u attribute”

df.A
不是
s
df.A
s
构造而来,忽略它是什么类型。

为了有类似需求的人的利益:我认为最好的解决方案是定义
DataFrame
的一个子类,并使用
\uGetItem\uuuuuu
逻辑进行干预

我最初的问题是基于这样一个假设,即
数据帧
被实现为一个容器,而从根本上说它不是。它更具活力,例如

>>> from pandas import Series, DataFrame
>>> s = Series([1, 2, 3, 4], name='x')
>>> df = DataFrame(s)
>>> s is df.x
False
因此,为了将列作为
系列
的子类检索,您需要修改
\uuuu getitem\uuuu

我已经在自己的包中实现了这一点,这可以作为一个示例:


不过,我很想听到任何人提出更优雅的解决方案

对于有类似需求的人来说:我认为最好的解决方案是定义
DataFrame
的子类,并使用
\uuu getitem\uuu
逻辑进行干预

我最初的问题是基于这样一个假设,即
数据帧
被实现为一个容器,而从根本上说它不是。它更具活力,例如

>>> from pandas import Series, DataFrame
>>> s = Series([1, 2, 3, 4], name='x')
>>> df = DataFrame(s)
>>> s is df.x
False
因此,为了将列作为
系列
的子类检索,您需要修改
\uuuu getitem\uuuu

我已经在自己的包中实现了这一点,这可以作为一个示例:

不过,我很想听到任何人提出更优雅的解决方案