Busque la fila donde los valores para la columna son máximos en un marco de datos de pandas

209

¿Cómo puedo encontrar la fila para la cual el valor de una columna específica es máximo ?

df.max() me dará el valor máximo para cada columna, no sé cómo obtener la fila correspondiente.

perezoso1
fuente
¿Es posible obtener los 2 valores principales? en lugar de solo el máximo?
AsheKetchum
55
Puede usar sort_valuesy obtener el índice:df.sort_values('col', ascending=False)[:2].index
lazy1
2
lazy1: evite ordenar innecesariamente una serie completa porque es O (N logN) en promedio, mientras que encontrar max / idxmax es solo O (N).
smci

Respuestas:

240

Utiliza la idxmaxfunción de pandas . Es sencillo:

>>> import pandas
>>> import numpy as np
>>> df = pandas.DataFrame(np.random.randn(5,3),columns=['A','B','C'])
>>> df
          A         B         C
0  1.232853 -1.979459 -0.573626
1  0.140767  0.394940  1.068890
2  0.742023  1.343977 -0.579745
3  2.125299 -0.649328 -0.211692
4 -0.187253  1.908618 -1.862934
>>> df['A'].argmax()
3
>>> df['B'].argmax()
4
>>> df['C'].argmax()
1
  • Alternativamente, también podría usar numpy.argmax, como numpy.argmax(df['A']): proporciona lo mismo y aparece al menos tan rápido como idxmaxen las observaciones superficiales.

  • idxmax() devuelve etiquetas de índices, no enteros.

    • Ejemplo ': si tiene valores de cadena como etiquetas de índice, como las filas' a 'a' e ', es posible que desee saber que el máximo se produce en la fila 4 (no en la fila' d ').
    • si desea la posición entera de esa etiqueta dentro de la Index, debe obtenerla manualmente (lo cual puede ser complicado ahora que se permiten etiquetas de fila duplicadas).

NOTAS HISTORICAS

  • idxmax()solía llamarse argmax()antes de 0.11
  • argmax fue desaprobado antes de 1.0.0 y eliminado por completo en 1.0.0
  • desde Pandas 0.16, argmaxsolía existir y realizar la misma función (aunque parecía funcionar más lentamente que idxmax).
    • argmaxLa función devolvió la posición entera dentro del índice de la ubicación de la fila del elemento máximo.
    • los pandas se movieron al uso de etiquetas de fila en lugar de índices enteros. Los índices enteros posicionales solían ser muy comunes, más comunes que las etiquetas, especialmente en aplicaciones donde las etiquetas de fila duplicadas son comunes.

Por ejemplo, considere este juguete DataFramecon una etiqueta de fila duplicada:

In [19]: dfrm
Out[19]: 
          A         B         C
a  0.143693  0.653810  0.586007
b  0.623582  0.312903  0.919076
c  0.165438  0.889809  0.000967
d  0.308245  0.787776  0.571195
e  0.870068  0.935626  0.606911
f  0.037602  0.855193  0.728495
g  0.605366  0.338105  0.696460
h  0.000000  0.090814  0.963927
i  0.688343  0.188468  0.352213
i  0.879000  0.105039  0.900260

In [20]: dfrm['A'].idxmax()
Out[20]: 'i'

In [21]: dfrm.iloc[dfrm['A'].idxmax()]  # .ix instead of .iloc in older versions of pandas
Out[21]: 
          A         B         C
i  0.688343  0.188468  0.352213
i  0.879000  0.105039  0.900260

Por lo tanto, aquí un uso ingenuo de idxmaxno es suficiente, mientras que la forma anterior de argmaxproporcionaría correctamente la ubicación posicional de la fila máxima (en este caso, la posición 9).

Este es exactamente uno de esos tipos desagradables de comportamientos propensos a errores en lenguajes escritos dinámicamente que hacen que este tipo de cosas sea tan desafortunado y que valga la pena vencer a un caballo muerto. Si está escribiendo código de sistemas y su sistema de repente se usa en algunos conjuntos de datos que no se limpian correctamente antes de unirse, es muy fácil terminar con etiquetas de fila duplicadas, especialmente etiquetas de cadena como un identificador CUSIP o SEDOL para activos financieros. No puede usar fácilmente el sistema de tipos para ayudarlo, y es posible que no pueda imponer la unicidad en el índice sin encontrarse con datos que faltan inesperadamente.

Entonces, te queda la esperanza de que tus pruebas unitarias cubran todo (no lo hicieron, o más probablemente nadie escribió ninguna prueba); de lo contrario (muy probablemente) solo te quedará esperando para ver si te topas con esto error en el tiempo de ejecución, en cuyo caso es probable que deba soltar muchas horas de trabajo de la base de datos a la que estaba enviando resultados, golpearse la cabeza contra la pared en IPython tratando de reproducir el problema manualmente, finalmente descubriendo que es porque soloidxmax puede informe la etiqueta de la fila máxima, y ​​luego se decepcionará de que ninguna función estándar obtenga automáticamente las posiciones de la fila máxima para usted, escribiendo una implementación con errores usted mismo, editando el código y rezando para que no vuelva a encontrarse con el problema.

ely
fuente
13
Basado en el penúltimo comentario allí, parece argminy argmaxseguirá siendo parte DataFramey la diferencia es solo si desea el índice o la etiqueta. idxmaxle dará la etiqueta de la ubicación donde se produce un máximo. argmaxle dará el índice entero en sí.
ely
44
¡La información provista para explicar la diferencia entre argmaxy idxmax, y cómo evitar errores con índice duplicado fue excelente! No lo noté hasta que leí tu comentario en la otra respuesta. ¡Gracias!
tupan
Con respecto al uso que le gustaría implementar, Pandas 0.24.1 señala lo siguiente: 'el comportamiento de argmaxse corregirá para devolver el máximo posicional en el futuro. Por ahora, use series.values.argmaxo np.argmax(np.array(values))para obtener la posición de la fila máxima.
Sam
1
de manera similar, el .ixmétodo del segundo ejemplo ha cambiado de nombre.iloc
Ma0
si su columna contiene solo valores nan, esto dará como resultado TypeError
Max Segal
77

También puedes probar idxmax:

In [5]: df = pandas.DataFrame(np.random.randn(10,3),columns=['A','B','C'])

In [6]: df
Out[6]: 
          A         B         C
0  2.001289  0.482561  1.579985
1 -0.991646 -0.387835  1.320236
2  0.143826 -1.096889  1.486508
3 -0.193056 -0.499020  1.536540
4 -2.083647 -3.074591  0.175772
5 -0.186138 -1.949731  0.287432
6 -0.480790 -1.771560 -0.930234
7  0.227383 -0.278253  2.102004
8 -0.002592  1.434192 -1.624915
9  0.404911 -2.167599 -0.452900

In [7]: df.idxmax()
Out[7]: 
A    0
B    8
C    7

p.ej

In [8]: df.loc[df['A'].idxmax()]
Out[8]: 
A    2.001289
B    0.482561
C    1.579985
Wes McKinney
fuente
Gracias Wes Documentación para idxmax () aquí: pandas.pydata.org/pandas-docs/dev/generated/…
Será
df.ix[df['A'].idxmax()].valuespara agarrar la matriz que quería. todavía funciona.
Yojimbo
2
Tenga en cuenta que debe tener cuidado al tratar de utilizar la salida de idxmaxun alimentador ixo loccomo un medio para dividir los datos y / o para obtener la ubicación posicional de la fila máxima. Debido a que puede tener duplicados en Index- vea la actualización de mi respuesta para ver un ejemplo.
ely
25

Ambas respuestas anteriores solo devolverían un índice si hay varias filas que toman el valor máximo. Si desea todas las filas, no parece tener una función. Pero no es difícil de hacer. A continuación se muestra un ejemplo de Serie; Lo mismo puede hacerse para DataFrame:

In [1]: from pandas import Series, DataFrame

In [2]: s=Series([2,4,4,3],index=['a','b','c','d'])

In [3]: s.idxmax()
Out[3]: 'b'

In [4]: s[s==s.max()]
Out[4]: 
b    4
c    4
dtype: int64
mxia
fuente
10
¡Gracias! versión para DataFrame:df[df['A'] == df['A'].max()]
Dennis Golomazov
Esta es la respuesta correcta (la versión DataFrame).
Gented
12
df.iloc[df['columnX'].argmax()]

argmax()proporcionaría el índice correspondiente al valor máximo para la columnaX. ilocse puede usar para obtener la fila del DataFrame df para este índice.

Nafeez Quraishi
fuente
4

La solución directa ".argmax ()" no funciona para mí.

El ejemplo anterior proporcionado por @ely

>>> import pandas
>>> import numpy as np
>>> df = pandas.DataFrame(np.random.randn(5,3),columns=['A','B','C'])
>>> df
      A         B         C
0  1.232853 -1.979459 -0.573626
1  0.140767  0.394940  1.068890
2  0.742023  1.343977 -0.579745
3  2.125299 -0.649328 -0.211692
4 -0.187253  1.908618 -1.862934
>>> df['A'].argmax()
3
>>> df['B'].argmax()
4
>>> df['C'].argmax()
1

devuelve el siguiente mensaje:

FutureWarning: 'argmax' is deprecated, use 'idxmax' instead. The behavior of 'argmax' 
will be corrected to return the positional maximum in the future.
Use 'series.values.argmax' to get the position of the maximum now.

Para que mi solución sea:

df['A'].values.argmax()
AntoineP
fuente
2
mx.iloc[0].idxmax()

Esta línea de código le dará cómo encontrar el valor máximo de una fila en el marco de datos, aquí mxestá el marco de datos e iloc[0]indica el índice 0.

Manjula Devi
fuente
1

El idmaxdel DataFrame devuelve el índice de etiqueta de la fila con el valor máximo y el comportamiento de argmaxdepende de la versión de pandas(en este momento devuelve una advertencia). Si desea utilizar el índice posicional , puede hacer lo siguiente:

max_row = df['A'].values.argmax()

o

import numpy as np
max_row = np.argmax(df['A'].values)

Tenga en cuenta que si usa se np.argmax(df['A'])comporta igual que df['A'].argmax().

Jonathan
fuente