web-dev-qa-db-fra.com

Pandas DataFrame - Trouve la 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() me donnera la valeur maximale pour chaque colonne, je ne sais pas comment obtenir la ligne correspondante.

155
lazy1

Vous avez juste besoin de la fonction argmax() (now appelée idxmax). 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 que depuis Pandas 0.16, argmax existe toujours et exécute la même fonction (bien qu'il semble fonctionner plus lentement que idxmax).

Vous pouvez également simplement 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 dans des observations superficielles.

Auparavant (comme indiqué dans les commentaires), il apparaissait que argmax existerait en tant que fonction distincte qui fournirait la position integer 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 maximum se produit à la ligne 4 (et non à la ligne "d"). Cependant, dans Pandas 0.16, toutes les méthodes énumérées ci-dessus fournissent uniquement le label à partir de la Index pour la ligne en question. Si vous voulez que le nombre entier de positions de cette étiquette dans la Index vous devez l’obtenir manuellement (qui peut être délicat maintenant que les étiquettes de lignes en double sont autorisées).

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

Par exemple, considérons 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 fournissait correctement l'emplacement positional de la rangée max (dans ce cas, la position 9).

C’est exactement un de ces types de comportements vicieux sujets à des bogues dans des langages à typage dynamique qui rend ce genre de chose si malheureux et qui vaut la peine d’être battu à mort. Si vous écrivez du code système et que votre système est soudainement utilisé sur des 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 lignes en double, en particulier des étiquettes de chaîne telles qu'un identifiant CUSIP ou SEDOL pour des actifs financiers. Vous ne pouvez pas facilement utiliser le système de types pour vous aider et vous ne pourrez peut-être pas imposer l'unicité de l'index sans rencontrer des données manquantes de manière inattendue. 

Donc, il ne vous reste plus qu'à 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), il ne vous reste plus qu'à attendre de voir s'il vous arrive de vous enfoncer dedans erreur au moment de l'exécution, auquel cas vous devez probablement laisser tomber de nombreuses heures de travail dans la base de données vers laquelle vous exportiez les résultats, cognez votre tête contre le mur dans IPython en essayant de reproduire manuellement le problème, en déterminant finalement que c'est parce que idxmax peut only signale le label de la rangée max, puis déçu qu'aucune fonction standard ne récupère automatiquement la positions de la rangée max pour vous, en écrivant vous-même une implémentation de bogue, en modifiant le code, et en priant, vous ne rencontrez plus le problème.

175
ely

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
65
Wes McKinney

Les deux réponses ci-dessus ne renverraient qu'un seul index s'il y a plusieurs lignes prenant la valeur maximale. Si vous voulez toutes les lignes, il ne semble pas y avoir de fonction ..__ Mais ce n’est pas difficile à faire. Vous trouverez ci-dessous 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
19
mxia
df.iloc[df['columnX'].argmax()]

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

5
Nafeez Quraishi

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()
1
AntoineP

Voici quelques exemples utiles qui parlent d’eux-mêmes.

np.random.seed(0)                                                                                                      
df = pd.DataFrame(
    [[1, 2, 9], [7, 5, 6], [4, 8, 3]], columns=list('ABC'), index=list('xyz'))                           

df                                                                                                                     

   A  B  C
x  1  2  9
y  7  5  6
z  4  8  3

Index du nombre maximum de lignes par colonne:

df.idxmax()                                                                                                            

A    y
B    z
C    x
dtype: object

# for a specific column, use
df['A'].idxmax()                                                                                                      
# 'y' 

Indice de colonne maximum par ligne:

df.idxmax(axis=1)                                                                                                     

x    C
y    A
z    B
dtype: object

Position entière de la rangée maximum par colonne:

df.idxmax().map(df.index.get_loc)                                                                                     

A    1
B    2
C    0
dtype: int64


# For a specific column, pass the label to `Index.get_loc`
df.index.get_loc(df['A'].idxmax())                                                                                   
# 1

df['A'].to_numpy().argmax()                                                                                           
# 1

Note
Dans une version ultérieure, Series.argmax sera le point de départ du retour de la position maximale INTEGER. Pour le moment, il a le même comportement que Series.idxmax et renvoie un message FutureWarning. Pour l'instant, df['A'].to_numpy().argmax().

Position entière de la colonne maximum par ligne:

df.idxmax(axis=1).map(df.columns.get_loc)                                                                             

x    2
y    0
z    1
dtype: int64

# For a specific row,
df.columns.get_loc(df.loc['x'].idxmax())                                                                              
# 2
0
cs95
mx.iloc[0].idxmax()

Cette ligne de code vous indiquera comment trouver la valeur maximale d'une ligne dans le cadre de données, ici «mx» est le cadre de données et iloc [0] indique le 0e index.

0
Manjula Devi

Les argmax et idmax du DataFrame renvoie l'index de libellé de la ligne avec la valeur maximale (au moins avec la version plus récente des pandas). Si vous souhaitez utiliser l'index positional, vous pouvez procéder comme suit:

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

numpy a été importé sous la forme np en tant que norme. Notez que si vous utilisez np.argmax(df['A']), l’indexation par étiquette est utilisée.

0
Jonathan