2016-10-20 6 views
1

Ich möchte eine DataFrame erstellen, die eine Anzahl von verschiedenenSeries Unterklassen ich definiert habe. Es scheint, dass die Unterklasse von der Series entfernt ist, wenn sie jedoch einer DataFrame zugeordnet ist.Python pandas: speichern Series Unterklasse als eine DataFrame Spalte

Hier ist ein Spielzeug Beispiel um das Problem zu veranschaulichen:

>>> 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' 

ich dieses Problem gesehen habe kann vorher #1713 angehoben worden ist, aber ich kann die aktuelle Lösung nicht erkennen. Da es so eine riesige Bibliothek ist, ist es schwierig, den verschiedenen PRs, Doc-Versionen usw. zu folgen. Und die Unterklassen-Mechanik scheint, soweit ich das beurteilen kann, nicht so gut beschrieben().

Antwort

0

Ich denke, Sie haben Pech, es sei denn, Sie definieren auch Ihre eigene pd.DataFrame Unterklasse. Und das wäre eine noch entmutigendere Aufgabe.

betrachten Sie dieses Beispiel

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.A nicht s ist. df.A wird von s erstellt und ignoriert, welcher Typ es ist.

0

Zum Vorteil für alle mit einem ähnlichen Bedarf: Ich denke, die beste Lösung ist, eine Unterklasse von DataFrame zu definieren und mit der __getitem__ Logik einzugreifen.

Meine ursprüngliche Frage basierte auf der Annahme, dass ein DataFrame als Container implementiert ist, was es grundsätzlich nicht ist. Es ist dynamischer, z ...

>>> from pandas import Series, DataFrame 
>>> s = Series([1, 2, 3, 4], name='x') 
>>> df = DataFrame(s) 
>>> s is df.x 
False 

Deshalb, um Spalten als Subklassen von Series abzurufen, werden Sie mit __getitem__ basteln müssen.

Ich habe implementiert dies in meinem eigenen Paket, die als Beispiel dienen könnte: https://github.com/jmackie4/activityio/blob/master/activityio/_util/types.py

ich daran interessiert wäre, wenn von jemandem mit einer eleganteren Lösung zu hören!

Verwandte Themen