Estoy tratando de encontrar el valor máximo de un cálculo en una columna en un marco de datos. Para hacer esto, estoy creando la columna de cálculo y luego invocando max() en ella.

df['two'] = df['one']/df['one'].index maximum = df['two'].max()

Esta es una operación lenta y me pregunto si es posible optimizarla evitando el uso de memoria para la columna de cálculo y simplemente calcular la columna sobre la marcha mientras realiza un seguimiento de su valor máximo. Puedo hacer esto en Python vainilla pero quiero la eficiencia de los pandas.

¡Gracias a cualquiera que pueda ayudarme!

2
puzzler 9 may. 2016 a las 22:59

3 respuestas

La mejor respuesta

Podemos intentar hacer trampa, pero necesitamos saber la fórmula / algoritmo exacto.

En su ejemplo, se puede hacer sin almacenar la columna:

maximum = (df.a/df.index).max()

Si es un cálculo más complejo, puede usar el método .assign():

maximum = df.assign(two=df.a/df.index)['two'].max()

Prueba:

In [19]: df
Out[19]:
    a  b  c
0   0  9  3
1   7  6  5
2   4  5  8
3   0  4  3
4   7  4  5
5   0  9  9
6   7  5  2
7   4  4  4
8   1  3  3
9   3  1  3
10  6  6  1
11  8  4  0
12  6  2  9
13  4  1  0
14  8  5  9

In [20]: df.assign(two=df.a/df.index)['two'].max()
Out[20]: 7.0

In [21]: (df.a/df.index).max()
Out[21]: 7.0
2
MaxU 9 may. 2016 a las 20:11

Esto debería ser muy eficiente en la memoria. Utiliza iterrows y un generador para max.

np.random.seed(0)
df = pd.DataFrame(np.random.randn(5,3), columns=list('abc'))

df
Out[107]: 
          a         b         c
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
2  0.950088 -0.151357 -0.103219
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.443863

>>> max(row.a / idx for  idx, row in df.iterrows() if idx)
2.2408931992014578

El if idx es para eliminar instancias donde el denominador es cero o Ninguno.

0
Alexander 9 may. 2016 a las 20:17

El problema es que sacrifica la eficiencia en la memoria por la eficiencia en el procesamiento.

Podrías escribir un bucle.

maximum = np.nan
for i in range(len(df.a)):
    if pd.isnull(maximum):
        maximum = df.a[i] / df.index[i]
    else:
        maximum = max(maximum, df.a[i] / df.index[i])
0
piRSquared 9 may. 2016 a las 20:13