una tablas seleccionar recorrer para leer insertar funciones filtrar filas fila datos data crear columnas columna python performance for-loop pandas

python - tablas - seleccionar columnas de un dataframe pandas



¿Cuál es la forma más eficiente de recorrer los marcos de datos con pandas? (10)

Quiero realizar mis propias operaciones complejas sobre datos financieros en marcos de datos de manera secuencial.

Por ejemplo, estoy usando el siguiente archivo MSFT CSV tomado de Yahoo Finance :

Date,Open,High,Low,Close,Volume,Adj Close 2011-10-19,27.37,27.47,27.01,27.13,42880000,27.13 2011-10-18,26.94,27.40,26.80,27.31,52487900,27.31 2011-10-17,27.11,27.42,26.85,26.98,39433400,26.98 2011-10-14,27.31,27.50,27.02,27.27,50947700,27.27 ....

Entonces hago lo siguiente:

#!/usr/bin/env python from pandas import * df = read_csv(''table.csv'') for i, row in enumerate(df.values): date = df.index[i] open, high, low, close, adjclose = row #now perform analysis on open/close based on date, etc..

¿Es esa la forma más eficiente? Dado el enfoque en la velocidad en pandas, supongo que debe haber alguna función especial para iterar a través de los valores de una manera en que uno también recupera el índice (posiblemente a través de un generador para que sea eficiente en memoria). df.iteritems desafortunadamente solo itera columna por columna.


Al igual que lo que se ha mencionado anteriormente, el objeto pandas es más eficiente cuando se procesa toda la matriz a la vez. Sin embargo, para aquellos que realmente necesitan recorrer un marco de datos de pandas para realizar algo, como yo, encontré al menos tres formas de hacerlo. He hecho una breve prueba para ver cuál de los tres consume menos tiempo.

t = pd.DataFrame({''a'': range(0, 10000), ''b'': range(10000, 20000)}) B = [] C = [] A = time.time() for i,r in t.iterrows(): C.append((r[''a''], r[''b''])) B.append(time.time()-A) C = [] A = time.time() for ir in t.itertuples(): C.append((ir[1], ir[2])) B.append(time.time()-A) C = [] A = time.time() for r in zip(t[''a''], t[''b'']): C.append((r[0], r[1])) B.append(time.time()-A) print B

Resultado:

[0.5639059543609619, 0.017839908599853516, 0.005645036697387695]

Probablemente esta no sea la mejor manera de medir el consumo de tiempo, pero es rápido para mí.

Aquí hay algunos pros y contras IMHO:

  • .iterrows (): devuelve elementos de índice y fila en variables separadas, pero significativamente más lento
  • .itertuples (): más rápido que .iterrows (), pero el índice de retorno junto con los elementos de fila, ir [0] es el índice
  • zip: el más rápido, pero sin acceso al índice de la fila

Como joris señaló, iterrows es mucho más lento que itertuples y itertuples es aproximadamente 100 veces mayor que iterrows , y probé la velocidad de ambos métodos en un DataFrame con 5027505 registros. El resultado es para iterrows , es 1200it / s, e 120000it / s.

Si usa itertuples , tenga en cuenta que cada elemento en el bucle for es un timbre nombrado, por lo que para obtener el valor en cada columna, puede consultar el siguiente código de ejemplo

>>> df = pd.DataFrame({''col1'': [1, 2], ''col2'': [0.1, 0.2]}, index=[''a'', ''b'']) >>> df col1 col2 a 1 0.1 b 2 0.2 >>> for row in df.itertuples(): ... print(row.col1, row.col2) ... 1, 0.1 2, 0.2


Las versiones más recientes de pandas ahora incluyen una función incorporada para iterar sobre filas.

for index, row in df.iterrows(): # do some logic here

O, si lo quieres más rápido usa itertuples()

Pero, la sugerencia de Unutbu de usar funciones numpy para evitar la iteración en filas producirá el código más rápido.


Otra sugerencia sería combinar groupby con cálculos vectorizados si los subconjuntos de las filas compartieran características que le permitieran hacerlo.


Pandas se basa en matrices NumPy. La clave para acelerar con las matrices NumPy es realizar sus operaciones en toda la matriz a la vez, nunca fila por fila o elemento por elemento.

Por ejemplo, si close es una matriz 1-d, y desea el cambio porcentual del día a día,

pct_change = close[1:]/close[:-1]

Esto calcula el conjunto completo de cambios porcentuales como una declaración, en lugar de

pct_change = [] for row in close: pct_change.append(...)

Así que trate de evitar el bucle de Python for i, row in enumerate(...) completo, y piense en cómo realizar sus cálculos con operaciones en toda la matriz (o marco de datos) como un todo, en lugar de fila por fila.


Por supuesto, la forma más rápida de iterar sobre un marco de datos es acceder a la ndarray numpy subyacente a través de df.values (como lo hace) o al acceder a cada columna por separado df.column_name.values . Como también desea tener acceso al índice, puede usar df.index.values para eso.

index = df.index.values column_of_interest1 = df.column_name1.values ... column_of_interestk = df.column_namek.values for i in range(df.shape[0]): index_value = index[i] ... column_value_k = column_of_interest_k[i]

¿No es pitónico? Por supuesto. Pero rápido.

Si desea exprimir más jugo fuera del circuito, querrá ver cython . Cython te permitirá ganar grandes incrementos de velocidad (piensa 10x-100x). Para obtener el máximo rendimiento, compruebe las vistas de memoria de cython .


Puede recorrer las filas transponiendo y luego llamando a iteritems:

for date, row in df.T.iteritems(): # do some logic here

No estoy seguro de la eficiencia en ese caso. Para obtener el mejor rendimiento posible en un algoritmo iterativo, es posible que desee explorar escribirlo en cython , por lo que podría hacer algo como:

def my_algo(ndarray[object] dates, ndarray[float64_t] open, ndarray[float64_t] low, ndarray[float64_t] high, ndarray[float64_t] close, ndarray[float64_t] volume): cdef: Py_ssize_t i, n float64_t foo n = len(dates) for i from 0 <= i < n: foo = close[i] - open[i] # will be extremely fast

Recomendaría escribir el algoritmo en Python puro primero, asegúrese de que funcione y vea qué tan rápido es: si no es lo suficientemente rápido, convierta las cosas a Cython de esta manera con un trabajo mínimo para obtener algo que sea tan rápido como el código C a mano. / C ++.



Tienes tres opciones:

Por index (el más simple):

>>> for index in df.index: ... print ("df[" + str(index) + "][''B'']=" + str(df[''B''][index]))

Con iterrows (más utilizados):

>>> for index, row in df.iterrows(): ... print ("df[" + str(index) + "][''B'']=" + str(row[''B'']))

Con itertuples (el más rápido):

>>> for row in df.itertuples(): ... print ("df[" + str(row.Index) + "][''B'']=" + str(row.B))

Tres opciones muestran algo como:

df[0][''B'']=125 df[1][''B'']=415 df[2][''B'']=23 df[3][''B'']=456 df[4][''B'']=189 df[5][''B'']=456 df[6][''B'']=12

Fuente: neural-networks.io


iterrows después de notar respuesta de , pero encontré que produce tuplas (índice, serie). No estoy seguro de cuál funcionaría mejor para ti, pero terminé usando el método itertuples para mi problema, que produce tuplas (index, row_value1 ...).

También hay iterkv , que itera a través de tuplas (columna, serie).