¿Procesando eficientemente las filas de DataFrame con una función de Python?

En muchos lugares de nuestro código de uso de Pandas, tenemos algún process(row) función de Python process(row) . Esa función se usa sobre DataFrame.iterrows() , tomando cada row , y procesando, y devolviendo un valor, que finalmente recostackmos en una nueva Series .

Me doy cuenta de que este patrón de uso elude la mayoría de los beneficios de rendimiento de la stack de Números / Pandas.

  1. ¿Cuál sería la mejor manera de hacer que este patrón de uso sea lo más eficiente posible?
  2. ¿Podemos hacerlo sin reescribir la mayor parte de nuestro código?

Otro aspecto de esta pregunta: ¿se pueden convertir todas estas funciones en una representación eficiente? Tengo mucho que aprender sobre la stack de números / scipy / Pandas, pero parece que para una lógica verdaderamente arbitraria, a veces es posible que solo necesites usar una architecture Python pura y lenta como la de arriba. ¿Es ese el caso?

Debes aplicar tu función a lo largo del eje = 1. La función recibirá una fila como argumento y todo lo que devuelva se recostackrá en un nuevo objeto de serie

 df.apply(you_function, axis=1) 

Ejemplo:

 >>> df = pd.DataFrame({'a': np.arange(3), 'b': np.random.rand(3)}) >>> df ab 0 0 0.880075 1 1 0.143038 2 2 0.795188 >>> def func(row): return row['a'] + row['b'] >>> df.apply(func, axis=1) 0 0.880075 1 1.143038 2 2.795188 dtype: float64 

En cuanto a la segunda parte de la pregunta: las operaciones por filas, incluso las optimizadas, utilizando pandas, no son la solución más rápida que existe. Ciertamente son mucho más rápidos que un python para bucle, pero no son los más rápidos. Puedes probar eso por medio de las operaciones de tiempo y verás la diferencia.

Algunas operaciones podrían convertirse a columnas orientadas (una en mi ejemplo podría convertirse fácilmente a solo df['a'] + df['b'] ), pero otras no. Especialmente si tiene muchas bifurcaciones, casos especiales u otra lógica que debe realizar en su fila. En ese caso, si la apply es demasiado lenta para usted, sugeriría “Cython-izing” su código. Cython juega muy bien con la API NumPy C y te dará la velocidad máxima que puedes alcanzar.

O puedes probar numba . 🙂