2012-06-23 14 views
9

Ähnlich wie this R question möchte ich eine Funktion für jedes Element in einer Serie (oder jeder Zeile in einem DataFrame) mit Pandas anwenden, aber als Argument für diese Funktion den Index oder die ID verwenden dieser Reihe. Nehmen wir als Beispiel an, dass man eine Liste von Tupeln der Form [(index_i, value_i), ..., (index_n, value_n)] erstellen möchte. Mit einem einfachen Python for-Schleife, kann ich tun: pandas row spezifisch anwenden

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

Aber es muss ein effizienter Weg, dies zu tun? Vielleicht etwas Panda-ähnliches wie Series.apply? In Wirklichkeit bin ich nicht besorgt (in diesem Fall), etwas Sinnvolles zurückzugeben, sondern mehr für die Effizienz von etwas wie "Anwenden". Irgendwelche Ideen?

Antwort

7

Wenn Sie die Methode apply mit einer Funktion verwenden, wird jedes Element in der Serie mit einer solchen Funktion zugeordnet. Z.B.

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

Was Sie tun möchten, ist einfach die Serie selbst aufzuzählen.

>>> list(enumerate(s)) 
[(0, 'six'), (1, 'seven'), (2, 'six'), (3, 'seven'), (4, 'six')] 

Was wäre, wenn Sie zum Beispiel die Zeichenfolge aller Entitäten summieren möchten?

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

[Bearbeiten]

Im Anschluss an den OPs für Präzisierungen Frage:

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

Eine komplexere Nutzung gelten würde dies sein nicht verwechseln Serie (1D) mit DataFrames (2D) http://pandas.pydata.org/pandas-docs/stable/dsintro.html#dataframe - da sehe ich nicht wirklich, wie man über Zeilen reden kann. Jedoch Sie Indizes in Ihrer Funktion durch eine neue Serie zu schaffen (apply Sie nicht eine Information über den aktuellen Index) enthalten können:

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

Auf jeden Fall würde ich vorschlagen, dass Sie zu anderen Datentypen wechseln große Speicherlecks zu vermeiden.

+0

Danke @ luke14free für den Zeiger über Aufzählung. Am Ende habe ich wahrscheinlich ein allzu simples Beispiel geliefert, aber Sie haben tatsächlich eine passende Antwort gegeben. Was ich wirklich will, ist etwas wie dein drittes Beispiel, mit der zusätzlichen Bedingung, dass der Exponent eine Funktion der Zeile oder des Indexes ist ... –

+0

Hey @CarsonFarmer - siehe meine letzte Änderung – luke14free

+0

Danke @ luke14free. Am Ende habe ich getan, was Sie vorgeschlagen haben, und mein Problem anders gelöst, indem ich meine Daten umstrukturiert habe. –

3

Hier ist eine nette Art und Weise, itertools der count und zip mit:

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

Leider nur als effizienter als enumerate(list(s))!

Verwandte Themen