Trouver la ligne où les valeurs de la colonne sont maximales dans un DataFrame pandas

209

Comment puis-je trouver la ligne pour laquelle la valeur d'une colonne spécifique est maximale ?

df.max() me donnera la valeur maximale pour chaque colonne, je ne sais pas comment obtenir la ligne correspondante.

lazy1
la source
Est-il possible d'obtenir les 2 premières valeurs? au lieu de seulement le max?
AsheKetchum
5
Vous pouvez utiliser sort_valueset obtenir l'index:df.sort_values('col', ascending=False)[:2].index
lazy1
2
lazy1: évitez de trier inutilement une série entière car c'est O (N logN) en moyenne, alors que trouver max / idxmax n'est que O (N).
smci

Réponses:

240

Utilisez la idxmaxfonction pandas . C'est simple:

>>> 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
  • Alternativement, vous pouvez également utiliser numpy.argmax, comme numpy.argmax(df['A'])- il fournit la même chose et apparaît au moins aussi vite que idxmaxdans les observations superficielles.

  • idxmax() renvoie des étiquettes d'indices, pas des entiers.

    • Exemple ': si vous avez des valeurs de chaîne comme étiquettes d'index, comme les lignes' a 'à' e ', vous voudrez peut-être savoir que le maximum se produit dans la ligne 4 (pas la ligne' d ').
    • si vous voulez la position entière de cette étiquette dans le, Indexvous devez l'obtenir manuellement (ce qui peut être délicat maintenant que les étiquettes de ligne en double sont autorisées).

NOTES HISTORIQUES:

  • idxmax()était appelé argmax()avant 0,11
  • argmax a été déprécié avant 1.0.0 et supprimé entièrement dans 1.0.0
  • de retour à partir de Pandas 0.16, argmaxexistait et remplissait la même fonction (mais semblait fonctionner plus lentement que idxmax).
    • argmaxLa fonction a renvoyé la position entière dans l'index de l'emplacement de la ligne de l'élément maximum.
    • les pandas sont passés à l'utilisation d'étiquettes de lignes au lieu d'indices entiers. Les indices entiers positionnels étaient très courants, plus courants que les étiquettes, en particulier dans les applications où les étiquettes de lignes en double sont courantes.

Par exemple, considérez ce jouet DataFrameavec une étiquette de ligne en double:

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

Donc, ici, une utilisation naïve de idxmaxne suffit pas, alors que l'ancienne forme de argmaxfournirait correctement la position emplacement de la ligne max (dans ce cas, la position 9).

C'est exactement l'un de ces types désagréables de comportements sujets aux bogues dans des langages typés dynamiquement qui rendent ce genre de chose si malheureux et qui vaut la peine de battre un cheval mort. Si vous écrivez du code système et que votre système est soudainement utilisé sur certains ensembles de données qui ne sont pas nettoyés correctement avant d'être joints, il est très facile de se retrouver avec des étiquettes de ligne en double, en particulier des étiquettes de chaîne comme un identifiant CUSIP ou SEDOL pour les actifs financiers. Vous ne pouvez pas facilement utiliser le système de type pour vous aider et vous ne pourrez peut-être pas appliquer l'unicité sur l'index sans rencontrer des données manquantes de manière inattendue.

Il vous reste donc à espérer que vos tests unitaires couvrent tout (ils ne l'ont pas fait, ou plus probablement personne n'a écrit de test) - sinon (très probablement) vous êtes juste laissé attendre pour voir si vous vous retrouvez erreur lors de l'exécution, auquel cas vous devrez probablement supprimer de nombreuses heures de travail de la base de données vers laquelle vous produisez les résultats, vous cogner la tête contre le mur dans IPython en essayant de reproduire manuellement le problème, pour finalement comprendre que c'est parce que neidxmax peut que signaler le libellé de la ligne max, puis être déçu qu'aucune fonction standard n'obtienne automatiquement les positions de la ligne max pour vous, en écrivant vous-même une implémentation de buggy, en éditant le code et en priant pour que vous ne rencontriez plus le problème.

ely
la source
13
Sur la base de l'avant-dernier commentaire, il ressemble à argminet argmaxrestera partie intégrante DataFrameet la différence est simplement de savoir si vous voulez l'index ou l'étiquette. idxmaxvous donnera l'étiquette de l'emplacement où un max se produit. argmaxvous donnera l'index entier lui-même.
le
4
Les informations fournies pour expliquer la différence entre argmaxet idxmaxet comment éviter les bogues avec un index dupliqué étaient excellentes! Je ne l'ai pas remarqué avant d'avoir lu votre commentaire dans l'autre réponse. Merci!
tupan
En ce qui concerne l'utilisation que vous souhaitez mettre en œuvre, Pandas 0.24.1 indique ce qui suit: «le comportement de argmaxsera corrigé pour renvoyer le maximum positionnel à l'avenir. Pour l'instant, utilisez series.values.argmaxou np.argmax(np.array(values))pour obtenir la position de la ligne maximale. '
Sam
1
de même, la .ixméthode du deuxième exemple a été renommée en.iloc
Ma0
si votre colonne ne contient que des valeurs nan, cela se traduira par TypeError
Max Segal
77

Vous pouvez également essayer 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

par exemple

In [8]: df.loc[df['A'].idxmax()]
Out[8]: 
A    2.001289
B    0.482561
C    1.579985
Wes McKinney
la source
Merci Wes. Documentation pour idxmax () ici: pandas.pydata.org/pandas-docs/dev/generated/…
Will
df.ix[df['A'].idxmax()].valuespour saisir le tableau que je voulais. fonctionne encore.
Yojimbo
2
Notez que vous devez être prudent en essayant d'utiliser la sortie de idxmaxcomme chargeur dans ixou loccomme moyen de sous-découper les données et / ou d'obtenir l'emplacement de position de la ligne max. Parce que vous pouvez avoir des doublons dans le Index- voir la mise à jour de ma réponse pour un exemple.
ely
25

Les deux réponses ci-dessus ne renverraient qu'un index s'il y a plusieurs lignes qui prennent la valeur maximale. Si vous voulez toutes les lignes, il ne semble pas y avoir de fonction. Mais ce n'est pas difficile à faire. Voici un exemple pour la série; la même chose peut être faite pour 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
la source
10
Merci! version pour DataFrame:df[df['A'] == df['A'].max()]
Dennis Golomazov
C'est la réponse réellement correcte (la version DataFrame).
gented
12
df.iloc[df['columnX'].argmax()]

argmax()fournirait l'index correspondant à la valeur maximale pour la colonneX. ilocpeut être utilisé pour obtenir la ligne du df DataFrame pour cet index.

Nafeez Quraishi
la source
4

La solution directe ".argmax ()" ne fonctionne pas pour moi.

L'exemple précédent fourni par @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

renvoie le message suivant:

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.

Pour que ma solution soit:

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

Cette ligne de code vous donnera comment trouver la valeur maximale à partir d'une ligne dans le cadre de données, voici mxle cadre de données et iloc[0]indique le 0e index.

Manjula Devi
la source
1

Le idmaxDataFrame renvoie l'index d'étiquette de la ligne avec la valeur maximale et le comportement de argmaxdépend de la version de pandas(en ce moment, il renvoie un avertissement). Si vous souhaitez utiliser l' index positionnel , vous pouvez effectuer les opérations suivantes:

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

ou

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

Notez que si vous utilisez np.argmax(df['A'])se comporte de la même manière que df['A'].argmax().

Jonathan
la source