2012-06-23 11 views
9

Podobna do this R question, Chciałbym zastosować funkcję do każdej pozycji w serii (lub każdego wiersza w DataFrame) przy użyciu Pandy, ale chcesz użyć jako argument do tej funkcji indeks lub identyfikator z tego rzędu. Jako trywialny przykład załóżmy, że chcemy utworzyć listę krotek formularza [(index_i, value_i), ..., (index_n, value_n)]. Za pomocą prostego Python dla pętli, mogę zrobić: specyficzne dla rzędu pand zastosowanie

In [1] L = [] 
In [2] s = Series(['six', 'seven', 'six', 'seven', 'six'], 
      index=['a', 'b', 'c', 'd', 'e']) 
In [3] for i, item in enumerate(s): 
      L.append((i,item)) 
In [4] L 
Out[4] [(0, 'six'), (1, 'seven'), (2, 'six'), (3, 'seven'), (4, 'six')] 

Ale musi być bardziej efektywny sposób to zrobić? Być może coś więcej Panda-takich jak Series.apply? W rzeczywistości nie martwię się (w tym przypadku) o zwrot nic znaczącego, ale bardziej o skuteczność czegoś w stylu "zastosuj". Jakieś pomysły?

Odpowiedz

7

Jeśli zastosujesz metodę apply z funkcją, to co się stanie, każdy element w Serii zostanie odwzorowany za pomocą takiej funkcji. Na przykład.

>>> s.apply(enumerate) 
a <enumerate object at 0x13cf910> 
b <enumerate object at 0x13cf870> 
c <enumerate object at 0x13cf820> 
d <enumerate object at 0x13cf7d0> 
e <enumerate object at 0x13ecdc0> 

To, co chcesz zrobić, to po prostu wyliczyć serię.

Co jeśli na przykład chcesz zsumować ciąg wszystkich elementów?

>>> ",".join(s) 
'six,seven,six,seven,six' 

Bardziej skomplikowane użycie zastosowanie byłoby to jedno:

>>> from functools import partial 
>>> s.apply(partial(map, lambda x: x*2)) 
a    ['ss', 'ii', 'xx'] 
b ['ss', 'ee', 'vv', 'ee', 'nn'] 
c    ['ss', 'ii', 'xx'] 
d ['ss', 'ee', 'vv', 'ee', 'nn'] 
e    ['ss', 'ii', 'xx'] 

[Edit]

następujące pytanie PO za Wyjaśnienie: Nie należy mylić Series (1D) z DataFrames (2D) http://pandas.pydata.org/pandas-docs/stable/dsintro.html#dataframe - ponieważ tak naprawdę nie widzę sposobu, w jaki można mówić o rzędach. Jednak można to indeksy w swojej funkcji, tworząc nową serię (za przyzwyczajenie daje żadnych informacji na temat bieżącego indeksu):

>>> Series([s[x]+" my index is: "+x for x in s.keys()], index=s.keys()) 
a  six index a 
b seven index b 
c  six index c 
d seven index d 
e  six index e 

Tak czy inaczej chciałbym zaproponować, aby przełączyć się do innych typów danych, aby uniknąć ogromne wycieki pamięci.

+0

Dzięki @ luke14free dla wskaźnika o wyliczeniu. Ostatecznie prawdopodobnie dostarczyłem zbyt uproszczony przykład, ale rzeczywiście dostarczyłeś odpowiednią odpowiedź. To, czego naprawdę chcę, to coś w rodzaju trzeciego przykładu, z dodanym warunkiem, który mówi, że wykładnik jest funkcją rzędu lub indeksu ... –

+0

Hej @CarsonFarmer - zobacz moją ostatnią edycję – luke14free

+0

Dzięki @ luke14free. W końcu zrobiłem to, co sugerowałeś, i rozwiązałeś mój problem w inny sposób, zmieniając moje dane. –

3

Oto zgrabny sposób, używając count itertools i zip:

import pandas as pd 
from itertools import count 

s = pd.Series(['six', 'seven', 'six', 'seven', 'six'], 
        index=['a', 'b', 'c', 'd', 'e']) 

In [4]: zip(count(), s) 
Out[4]: [(0, 'six'), (1, 'seven'), (2, 'six'), (3, 'seven'), (4, 'six')] 

Niestety, tylko jako skuteczny niż enumerate(list(s))!

Powiązane problemy