Pandas DataFrame-trouver une ligne où les valeurs de la colonne sont maximales

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

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

132
demandé sur piRSquared 2012-04-18 07:59:55

5 réponses

, Vous avez juste besoin de la argmax() (maintenant appelé idxmax) fonction. 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

Cette fonction a été mise à jour sous le nom idxmax dans L'API Pandas, bien qu'à partir de Pandas 0.16, argmax existe toujours et exécute la même fonction (bien que semble fonctionner plus lentement que idxmax).

Vous pouvez également utiliser numpy.argmax, tel que numpy.argmax(df['A']) - Il fournit la même chose que l'une des deux fonctions pandas, et apparaît au moins aussi vite que idxmax en rapide observation.

Précédemment (comme indiqué dans les commentaires), il est apparu que argmax existerait comme une fonction distincte qui fournissait la Position entière dans l'index de l'emplacement de la ligne de l'élément maximum. Par 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 max se produit dans la ligne 4 (pas la ligne 'd'). Cependant, dans pandas 0.16, toutes les méthodes listées ci-dessus ne fournissent que l'étiquette du Index pour la ligne en question, et si vous voulez l'entier de position de cette étiquette dans le Index, Vous devez l'obtenir manuellement (ce qui peut être difficile maintenant que les étiquettes de ligne en double sont autorisées).

En général, je pense que le passage à un comportement similaire à idxmax pour les trois approches (argmax, qui existe toujours, idxmax et numpy.argmax) est une mauvaise chose, car il est très courant d'exiger l'emplacement entier positionnel d'un maximum, peut-être même plus commun que de vouloir l'étiquette de cela emplacement positionnel dans certains index, en particulier dans les applications où les étiquettes de ligne en double sont courantes.

Par exemple, considérez ce jouet DataFrame avec 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.ix[dfrm['A'].idxmax()]
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 idxmax n'est pas suffisante, alors que l'ancienne forme de argmax fournirait correctement l'emplacement positionnel de la ligne max (dans ce cas, position 9).

C'est exactement l'un de ces types de comportements sujets aux bogues dans les langages typés dynamiquement qui cela rend ce genre de chose si malheureux, et 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 pouvez pas être en mesure d'appliquer l'unicité sur l'index sans rencontrer de façon inattendue les données manquantes.

Il vous reste donc à espérer que vos tests unitaires ont tout couvert (ils ne l'ont pas fait, ou plus probablement personne n'a écrit de tests) - sinon (très probablement) vous attendez de voir si vous vous retrouvez dans cette erreur lors de l'exécution, auquel cas vous devrez probablement passer de nombreuses heures de travail à partir de la base de données parce que idxmax ne peut que signaler lelabel de la ligne max, puis être déçu qu'aucune fonction standard n'obtienne automatiquement lespositions de la ligne max pour vous, en écrivant vous-même une implémentation boguée, en éditant le code et en priant de ne plus rencontrer le problème.

150
répondu ely 2017-09-11 17:10:53

, Vous pouvez également essayer de 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
62
répondu Wes McKinney 2017-11-26 14:29:55

Les deux réponses ci-dessus ne retourneraient qu'un index s'il y a plusieurs lignes qui prennent la valeur maximale. Si vous voulez toutes les lignes, il ne semble pas avoir de fonction. Mais il n'est pas difficile à faire. Voici un exemple pour les séries; 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
19
répondu mxia 2014-09-10 20:55:04
df.iloc[df['columnX'].argmax()]

argmax() fournirait l'index correspondant à la valeur max pour le columnX. iloc peut être utilisé pour obtenir la ligne du DataFrame df pour cet index.

3
répondu nAQ 2018-06-10 01:13:44

Les argmax et idmax du DataFrame renvoient l'index d'étiquette de la ligne avec la valeur maximale (au moins avec une version plus récente de pandas). Si vous voulez utiliser l'index de position , Vous pouvez faire ce qui suit:

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

numpy a été importé comme np comme c'est la norme. Notez que si vous utilisez np.argmax(df['A']), l'indexation des étiquettes est utilisée.

0
répondu Jonathan 2017-07-05 19:00:44