¿Por qué la función “aplicar” de mi Pandas no hace referencia a varias columnas funcionando?

Tengo algunos problemas con la función de aplicación de Pandas, cuando uso varias columnas con el siguiente dataframe

df = DataFrame ({'a' : np.random.randn(6), 'b' : ['foo', 'bar'] * 3, 'c' : np.random.randn(6)}) 

y la siguiente función

 def my_test(a, b): return a % b 

Cuando bash aplicar esta función con:

 df['Value'] = df.apply(lambda row: my_test(row[a], row[c]), axis=1) 

Me sale el mensaje de error:

 NameError: ("global name 'a' is not defined", u'occurred at index 0') 

No entiendo este mensaje, definí el nombre correctamente.

Apreciaría cualquier ayuda en este asunto.

Actualizar

Gracias por tu ayuda. De hecho, cometí algunos errores de syntax con el código, el índice se debe poner ”. Sin embargo, sigo teniendo el mismo problema al usar una función más compleja como:

 def my_test(a): cum_diff = 0 for ix in df.index(): cum_diff = cum_diff + (a - df['a'][ix]) return cum_diff 

Parece que olvidaste el '' de tu cuerda.

 In [43]: df['Value'] = df.apply(lambda row: my_test(row['a'], row['c']), axis=1) In [44]: df Out[44]: abc Value 0 -1.674308 foo 0.343801 0.044698 1 -2.163236 bar -2.046438 -0.116798 2 -0.199115 foo -0.458050 -0.199115 3 0.918646 bar -0.007185 -0.001006 4 1.336830 foo 0.534292 0.268245 5 0.976844 bar -0.773630 -0.570417 

Por cierto, en mi opinión, la siguiente forma es más elegante:

 In [53]: def my_test2(row): ....: return row['a'] % row['c'] ....: In [54]: df['Value'] = df.apply(my_test2, axis=1) 

Si solo desea calcular (columna a)% (columna b), no necesita apply , simplemente hágalo directamente:

 In [7]: df['a'] % df['c'] Out[7]: 0 -1.132022 1 -0.939493 2 0.201931 3 0.511374 4 -0.694647 5 -0.023486 Name: a 

Digamos que queremos aplicar una función add5 a las columnas ‘a’ y ‘b’ de DataFrame df

 def add5(x): return x+5 df[['a', 'b']].apply(add5) 

Todas las sugerencias anteriores funcionan, pero si desea que sus cálculos sean más eficientes, debe aprovechar las operaciones de vectores numpy (como se indica aquí) .

 import pandas as pd import numpy as np df = pd.DataFrame ({'a' : np.random.randn(6), 'b' : ['foo', 'bar'] * 3, 'c' : np.random.randn(6)}) 

Ejemplo 1: bucle con pandas.apply() :

 %%timeit def my_test2(row): return row['a'] % row['c'] df['Value'] = df.apply(my_test2, axis=1) 

La carrera más lenta tomó 7.49 veces más que la más rápida. Esto podría significar que se está almacenando en caché un resultado intermedio. 1000 bucles, lo mejor de 3: 481 µs por bucle

Ejemplo 2: vectorizar utilizando pandas.apply() :

 %%timeit df['a'] % df['c'] 

La carrera más lenta tomó 458.85 veces más que la más rápida. Esto podría significar que se está almacenando en caché un resultado intermedio. 10000 bucles, lo mejor de 3: 70.9 µs por bucle

Ejemplo 3: vectorizar utilizando matrices numpy:

 %%timeit df['a'].values % df['c'].values 

La carrera más lenta tomó 7.98 veces más que la más rápida. Esto podría significar que se está almacenando en caché un resultado intermedio. 100000 bucles, lo mejor de 3: 6.39 µs por bucle

Por lo tanto, la vectorización utilizando matrices numpy mejoró la velocidad en casi dos órdenes de magnitud.

Esto es lo mismo que la solución anterior, pero he definido la función en df.apply en sí misma:

 df['Value'] = df.apply(lambda row: row['a']%row['c'], axis=1) 

He dado la comparación de los tres mencionados anteriormente.

Usando valores

  % timeit df ['valor'] = df ['a']. valores% df ['c']. valores 

139 µs ± 1.91 µs por bucle (media ± desviación estándar de 7 carreras, 10000 bucles cada una)

Sin valores

  % timeit df ['valor'] = df ['a']% df ['c'] 

216 µs ± 1.86 µs por bucle (media ± desviación estándar de 7 ejecuciones, 1000 bucles cada una)

Aplicar la función

  % timeit df ['Valor'] = df.apply (fila lambda: fila ['a']% fila ['c'], eje = 1) 

474 µs ± 5.07 µs por bucle (media ± desviación estándar de 7 ejecuciones, 1000 bucles cada una)