2012-06-23 43 views
9

Similar a this R question, me gustaría aplicar una función a cada elemento de una serie (o cada fila en un DataFrame) usando pandas, pero quiero usar como argumento para esta función el índice o id. de esa fila. Como un ejemplo trivial, supongamos que uno quiere crear una lista de tuplas de la forma [(index_i, value_i), ..., (index_n, value_n)]. Utilizando un simple bucle for Python, no puedo hacer: aplicación específica de fila de pandas

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

Pero tiene que haber una manera más eficiente de hacer esto? Tal vez algo más Panda-ish como Series.apply? En realidad, no estoy preocupado (en este caso) por devolver algo significativo, sino más por la eficiencia de algo así como 'aplicar'. ¿Algunas ideas?

Respuesta

7

Si utiliza el método apply con una función, lo que ocurre es que cada elemento de la serie se correlacionará con dicha función. P.ej.

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

Lo que quieres hacer es simplemente enumerar la serie en sí.

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

¿Qué ocurre si, por ejemplo, desea sumar la cadena de todas las entidades?

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

Un uso más complejo de aplicar sería éste:

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

[Editar]

Tras la pregunta de la OP aclaraciones: No se debe confundir la serie (1D) con DataFrames (2D) http://pandas.pydata.org/pandas-docs/stable/dsintro.html#dataframe - ya que realmente no veo cómo se puede hablar de filas. Sin embargo, puede incluir índices en su función mediante la creación de una nueva serie (de no le dará ninguna información sobre el índice actual):

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

De todos modos yo sugeriría que cambie a otro tipo de datos para evitar grandes pérdidas de memoria.

+0

Gracias @ luke14free para el puntero sobre enumerar. Al final, probablemente proporcioné un ejemplo excesivamente simplista, pero realmente proporcionaste una respuesta adecuada. Sin embargo, lo que realmente quiero es algo así como su tercer ejemplo, con la condición añadida de que, por ejemplo, el exponente es una función de la fila o índice ... –

+0

Hola @CarsonFarmer - ver mi última edición – luke14free

+0

Gracias @ luke14free. Al final, hice lo que me sugirió y resolví mi problema de otra manera mediante la reestructuración de mis datos. –

3

Aquí está una manera ordenada, utilizando de itertools count y 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')] 

Por desgracia, sólo como eficiente que enumerate(list(s))!

Cuestiones relacionadas