367 votes

Trouver la ligne où la valeur de la colonne est maximale dans un DataFrame pandas.

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

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

1 votes

Est-il possible d'obtenir les deux valeurs les plus élevées au lieu de la valeur maximale ?

9 votes

Vous pouvez utiliser sort_values et obtenir l'index : df.sort_values('col', ascending=False)[:2].index

8 votes

Paresseux1 : éviter de trier inutilement une série entière parce que c'est O(N logN) en moyenne, alors que trouver max/idxmax est seulement O(N).

385voto

EMS Points 9249

Utilisez les pandas 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
  • Vous pouvez également utiliser numpy.argmax tels que numpy.argmax(df['A']) -- il fournit la même chose, et apparaît au moins aussi rapidement que idxmax dans des observations superficielles.

  • idxmax() renvoie des étiquettes d'indices, et non 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 (et non dans la ligne "d").
    • si vous souhaitez connaître la position entière de cette étiquette dans la fenêtre Index vous devez l'obtenir manuellement (ce qui peut être délicat maintenant que les étiquettes de ligne dupliquées sont autorisées).

NOTES HISTORIQUES :

  • idxmax() s'appelait autrefois argmax() avant 0,11
  • argmax a été déprécié avant la version 1.0.0 et entièrement supprimé dans la version 1.0.0.
  • Retour à partir de Pandas 0.16, argmax existaient et remplissaient la même fonction (bien qu'ils semblaient fonctionner plus lentement qu'auparavant). idxmax ).
    • argmax a renvoyé le position entière dans l'index de l'emplacement de la ligne de l'élément maximal.
    • pandas utilise désormais des étiquettes de ligne au lieu d'indices entiers. Les indices d'entiers positionnels étaient autrefois très courants, plus courants que les étiquettes, notamment dans les applications où les étiquettes de rangées dupliquées sont fréquentes.

Par exemple, considérez ce jouet DataFrame avec une étiquette de ligne dupliquée :

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 idxmax n'est pas suffisante, alors que l'ancienne forme de argmax fournirait correctement le positionnel emplacement de la ligne max (dans ce cas, la position 9).

C'est exactement l'un de ces types de comportements susceptibles d'entraîner des bogues dans les langages typés dynamiquement qui rend ce genre de choses 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 des ensembles de données qui n'ont pas été 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 faire respecter l'unicité de l'index sans vous retrouver avec des données manquantes inattendues.

Il ne vous reste plus qu'à espérer que vos tests unitaires couvrent tout (ce n'est pas le cas, ou plus vraisemblablement personne n'a écrit de tests) -- sinon (c'est le plus probable), il ne vous reste plus qu'à attendre de voir si vous tombez sur cette erreur au moment de l'exécution, auquel cas vous devrez probablement abandonner plusieurs heures de travail depuis la base de données vers laquelle vous sortiez les résultats, vous frapper la tête contre le mur dans IPython en essayant de reproduire manuellement le problème, pour finalement découvrir que c'est parce que idxmax peut uniquement signaler le étiquette de la rangée max, et ensuite être déçu qu'aucune fonction standard n'obtienne automatiquement la postes de la ligne max pour vous, en écrivant vous-même une implémentation boguée, en modifiant le code et en priant pour ne plus rencontrer le problème.

16 votes

En se basant sur l'avant-dernier commentaire, on dirait que argmin et argmax fera toujours partie de DataFrame et la différence est juste de savoir si vous voulez l'index ou l'étiquette. idxmax vous donnera l'étiquette de l'endroit où se produit un maximum. argmax vous donnera l'indice entier lui-même.

4 votes

Les informations fournies pour expliquer la différence entre argmax et idxmax et comment éviter les bugs avec les index dupliqués était génial ! Je n'avais pas remarqué cela avant de lire votre commentaire dans l'autre réponse. Merci !

0 votes

En ce qui concerne l'utilisation que vous souhaitez mettre en œuvre, Pandas 0.24.1 indique ce qui suit : "le comportement de argmax sera corrigé pour retourner le maximum positionnel dans le futur. Pour l'instant, utilisez series.values.argmax ou np.argmax(np.array(values)) pour obtenir la position de la rangée maximale.

102voto

Wes McKinney Points 17545

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

0 votes

Merci Wes. Documentation pour idxmax() ici : pandas.pydata.org/pandas-docs/dev/generated/

0 votes

df.ix[df['A'].idxmax()].values pour récupérer le tableau que je voulais. Ça marche toujours.

2 votes

Notez que vous devez être prudent en essayant d'utiliser la sortie de idxmax pour alimenter les ix ou loc comme moyen de subdiviser les données et/ou d'obtenir l'emplacement de la rangée maximale. Comme il peut y avoir des doublons dans le fichier Index - voir la mise à jour de ma réponse pour un exemple.

38voto

mxia Points 1

Les deux réponses ci-dessus ne renvoient qu'un seul 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. Vous trouverez ci-dessous un exemple pour les séries ; la même chose peut être faite pour les 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

26 votes

Merci ! version pour DataFrame : df[df['A'] == df['A'].max()]

0 votes

Il s'agit en fait de la réponse correcte (la version DataFrame).

23voto

Nafeez Quraishi Points 1165
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.

16voto

Morty Points 31

Une solution plus compacte et plus lisible utilisant query() c'est comme ça :

import pandas as pd

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

# find row with maximum A
df.query('A == A.max()')

Il renvoie également un DataFrame au lieu d'une série, ce qui serait pratique pour certains cas d'utilisation.

0 votes

Je cherchais quelque chose comme ça. Merci beaucoup.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X