example python numpy pandas numba

python - example - La forma más rápida de procesar numéricamente 2d-array: dataframe vs series vs array vs numba



pandas dataframe (2)

Editar para agregar : no creo que los puntos de referencia numba sean justos, notas debajo

Estoy tratando de comparar diferentes enfoques para procesar datos numéricamente para el siguiente caso de uso:

  1. Conjunto de datos bastante grande (más de 100.000 registros)
  2. Más de 100 líneas de código bastante simple (z = x + y)
  3. No es necesario ordenar o indexar

En otras palabras, no se necesita la generalidad completa de series y marcos de datos, aunque se incluyen aquí b / c, siguen siendo formas convenientes de encapsular los datos y, a menudo, hay un procesamiento previo o posterior que requiere la generalidad de los pandas. matrices numpy.

Pregunta : En base a este caso de uso, ¿son adecuados los siguientes puntos de referencia y, de no ser así, cómo puedo mejorarlos?

# importing pandas, numpy, Series, DataFrame in standard way from numba import jit nobs = 10000 nlines = 100 def proc_df(): df = DataFrame({ ''x'': np.random.randn(nobs), ''y'': np.random.randn(nobs) }) for i in range(nlines): df[''z''] = df.x + df.y return df.z def proc_ser(): x = Series(np.random.randn(nobs)) y = Series(np.random.randn(nobs)) for i in range(nlines): z = x + y return z def proc_arr(): x = np.random.randn(nobs) y = np.random.randn(nobs) for i in range(nlines): z = x + y return z @jit def proc_numba(): xx = np.random.randn(nobs) yy = np.random.randn(nobs) zz = np.zeros(nobs) for j in range(nobs): x, y = xx[j], yy[j] for i in range(nlines): z = x + y zz[j] = z return zz

Resultados (Win 7, estación de trabajo Xeon de 3 años de antigüedad (quad-core). Distribución de anaconda estándar y reciente o muy cercana).

In [1251]: %timeit proc_df() 10 loops, best of 3: 46.6 ms per loop In [1252]: %timeit proc_ser() 100 loops, best of 3: 15.8 ms per loop In [1253]: %timeit proc_arr() 100 loops, best of 3: 2.02 ms per loop In [1254]: %timeit proc_numba() 1000 loops, best of 3: 1.04 ms per loop # may not be valid result (see note below)

Editar para agregar (respuesta a jeff) resultados alternativos de pasar df / series / array a funciones en lugar de crearlas dentro de funciones (es decir, mover las líneas de código que contienen ''randn'' de la función interna a la función externa):

10 loops, best of 3: 45.1 ms per loop 100 loops, best of 3: 15.1 ms per loop 1000 loops, best of 3: 1.07 ms per loop 100000 loops, best of 3: 17.9 µs per loop # may not be valid result (see note below)

Nota sobre los resultados de numba : creo que el compilador numba debe estar optimizando en el ciclo for y reduciendo el ciclo for a una única iteración. No lo sé, pero es la única explicación que puedo dar, ya que no podría ser 50 veces más rápido que numpy, ¿verdad? Pregunta de seguimiento aquí: ¿Por qué numba es más rápido que numpy aquí?


Bueno, realmente no estás cronometrando las mismas cosas aquí (o más bien, estás cronometrando diferentes aspectos).

P.ej

In [6]: x = Series(np.random.randn(nobs)) In [7]: y = Series(np.random.randn(nobs)) In [8]: %timeit x + y 10000 loops, best of 3: 131 µs per loop In [9]: %timeit Series(np.random.randn(nobs)) + Series(np.random.randn(nobs)) 1000 loops, best of 3: 1.33 ms per loop

Entonces [8] veces la operación real, mientras que [9] incluye la sobrecarga para la creación de la serie (y la generación de números aleatorios) MÁS la operación real

Otro ejemplo es proc_ser vs proc_df . El proc_df incluye la sobrecarga de la asignación de una columna particular en el DataFrame (que en realidad es diferente para una creación inicial y posterior reasignación).

Entonces crea la estructura (también puedes cronometrar eso, pero eso es un problema aparte). Realice exactamente la misma operación y cítelos.

Además, dices que no necesitas alineación. Pandas te da esto de manera predeterminada (y no es una forma realmente fácil de desactivarlo, aunque es solo una simple comprobación si ya están alineados). Mientras esté en Numba, debe alinearlos ''manualmente''.


Siguiendo con la respuesta de @Jeff. El código se puede optimizar aún más.

nobs = 10000 x = pd.Series(np.random.randn(nobs)) y = pd.Series(np.random.randn(nobs)) %timeit proc_ser() %timeit x + y %timeit x.values + y.values 100 loops, best of 3: 11.8 ms per loop 10000 loops, best of 3: 107 µs per loop 100000 loops, best of 3: 12.3 µs per loop