Suchen Sie in einem Pandas-DataFrame nach einer Zeile, in der die Werte für die Spalte maximal sind

208

Wie finde ich die Zeile, für die der Wert einer bestimmten Spalte maximal ist ?

df.max() gibt mir den Maximalwert für jede Spalte, ich weiß nicht, wie ich die entsprechende Zeile bekommen soll.

faul1
quelle
Ist es möglich, die Top 2 Werte zu bekommen? statt nur der max?
AsheKetchum
5
Sie können sort_valuesden Index verwenden und erhalten:df.sort_values('col', ascending=False)[:2].index
faul1
2
faul1: Vermeiden Sie unnötiges Sortieren einer ganzen Reihe, da es im Durchschnitt O (N logN) ist, während das Finden von max / idxmax nur O (N) ist.
smci

Antworten:

240

Verwenden Sie die Pandas- idxmaxFunktion. Es ist unkompliziert:

>>> 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
  • Alternativ können Sie auch Folgendes verwenden numpy.argmax: numpy.argmax(df['A'])- Es bietet dasselbe und erscheint mindestens so schnell wie idxmaxbei flüchtigen Beobachtungen.

  • idxmax() Gibt Indexbezeichnungen zurück, keine Ganzzahlen.

    • Beispiel ': Wenn Sie Zeichenfolgenwerte als Indexbezeichnungen haben, wie z. B. die Zeilen' a 'bis' e ', möchten Sie möglicherweise wissen, dass das Maximum in Zeile 4 auftritt (nicht in Zeile' d ').
    • Wenn Sie die ganzzahlige Position dieser Beschriftung innerhalb der möchten Index, müssen Sie sie manuell abrufen (was jetzt schwierig sein kann, da doppelte Zeilenbeschriftungen zulässig sind).

HISTORISCHE ANMERKUNGEN:

  • idxmax()wurde früher vor 0.11 aufgerufenargmax()
  • argmax wurde vor 1.0.0 veraltet und in 1.0.0 vollständig entfernt
  • zurück ab Pandas 0.16, argmaxexistierte früher und führte dieselbe Funktion aus (obwohl es langsamer zu laufen schien als idxmax).
    • argmaxDie Funktion gab die ganzzahlige Position innerhalb des Index der Zeilenposition des maximalen Elements zurück.
    • Pandas verwendeten Zeilenbeschriftungen anstelle von Ganzzahlindizes. Positionszahlige Indizes waren früher sehr häufig, häufiger als Beschriftungen, insbesondere in Anwendungen, in denen doppelte Zeilenbeschriftungen häufig sind.

Betrachten Sie dieses Spielzeug beispielsweise DataFramemit einem doppelten Zeilenetikett:

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

Hier reicht also eine naive Verwendung von idxmaxnicht aus, während die alte Form von argmaxdie Positionsposition der maximalen Zeile (in diesem Fall Position 9) korrekt angeben würde .

Dies ist genau eine dieser bösen Arten von fehleranfälligen Verhaltensweisen in dynamisch getippten Sprachen, die solche Dinge so unglücklich machen und es wert sind, ein totes Pferd zu schlagen. Wenn Sie Systemcode schreiben und Ihr System plötzlich für einige Datensätze verwendet wird, die vor dem Zusammenfügen nicht ordnungsgemäß bereinigt wurden, kann es sehr leicht zu doppelten Zeilenbeschriftungen kommen, insbesondere zu Zeichenfolgenbeschriftungen wie einer CUSIP- oder SEDOL-Kennung für finanzielle Vermögenswerte. Sie können das Typsystem nicht einfach verwenden, um Ihnen zu helfen, und Sie können möglicherweise die Eindeutigkeit des Index nicht erzwingen, ohne auf unerwartet fehlende Daten zu stoßen.

Sie haben also die Hoffnung, dass Ihre Komponententests alles abdecken (sie haben es nicht getan oder wahrscheinlich hat niemand irgendwelche Tests geschrieben) - ansonsten müssen Sie (höchstwahrscheinlich) nur warten, um zu sehen, ob Sie sich darauf einlassen Fehler zur Laufzeit, in diesem Fall sind Sie wahrscheinlich viele Stunden im wert von Arbeit aus der Datenbank löschen , gehen müssen Sie Ergebnisse wurden zur Ausgabe an, den Kopf gegen die Wand in IPython manuell das Problem zu reproduzieren versuchen , Knall, herauszufinden schließlich heraus , dass es da ist idxmaxkann nur Melden Sie die Bezeichnung der maximalen Zeile und lassen Sie sich dann enttäuschen, dass keine Standardfunktion automatisch die Positionen der maximalen Zeile für Sie abruft. Schreiben Sie selbst eine fehlerhafte Implementierung, bearbeiten Sie den Code und beten Sie, dass Sie nicht erneut auf das Problem stoßen.

ely
quelle
13
Basierend auf dem vorletzten Kommentar dort sieht es so aus argminund argmaxwird ein Teil davon bleiben, DataFrameund der Unterschied besteht nur darin, ob Sie den Index oder das Label wollen. idxmaxgibt Ihnen die Bezeichnung des Ortes, an dem ein Maximum auftritt. argmaxgibt Ihnen die Index-Ganzzahl selbst.
ely
4
Die Informationen zur Erklärung des Unterschieds zwischen argmaxund idxmaxund zur Vermeidung von Fehlern mit doppeltem Index waren großartig! Ich habe das nicht bemerkt, bis ich Ihren Kommentar in der anderen Antwort gelesen habe. Vielen Dank!
Tupan
In Bezug auf die Verwendung, die Sie implementieren möchten, weist Pandas 0.24.1 auf Folgendes hin: 'Das Verhalten von argmaxwird korrigiert, um in Zukunft das Positionsmaximum zurückzugeben. Verwenden Sie vorerst series.values.argmaxoder np.argmax(np.array(values)), um die Position der maximalen Zeile abzurufen. '
Sam
1
In ähnlicher Weise wurde die .ixMethode des zweiten Beispiels in.iloc
Ma0
Wenn Ihre Spalte nur Nanowerte enthält, führt dies zu TypeError
Max Segal
77

Sie könnten auch versuchen 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

z.B

In [8]: df.loc[df['A'].idxmax()]
Out[8]: 
A    2.001289
B    0.482561
C    1.579985
Wes McKinney
quelle
Danke Wes. Dokumentation für idxmax () hier: pandas.pydata.org/pandas-docs/dev/generated/…
Will
df.ix[df['A'].idxmax()].valuesum das Array zu greifen, das ich wollte. funktioniert noch.
Yojimbo
2
Beachten Sie, dass Sie vorsichtig sein müssen, wenn Sie versuchen, die Ausgabe von idxmaxals Feeder in ixoder locals Mittel zum Unterteilen der Daten und / oder zum Ermitteln der Positionsposition der maximalen Zeile zu verwenden. Weil Sie Duplikate in der haben können Index- siehe das Update zu meiner Antwort für ein Beispiel.
ely
25

Beide obigen Antworten würden nur einen Index zurückgeben, wenn mehrere Zeilen den Maximalwert annehmen. Wenn Sie alle Zeilen möchten, scheint es keine Funktion zu geben. Aber es ist nicht schwer zu tun. Unten finden Sie ein Beispiel für Serien. Das Gleiche gilt für 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
quelle
10
Vielen Dank! Version für DataFrame:df[df['A'] == df['A'].max()]
Dennis Golomazov
Dies ist die tatsächlich richtige Antwort (die DataFrame-Version).
Gented
12
df.iloc[df['columnX'].argmax()]

argmax()würde den Index liefern, der dem Maximalwert für die Spalte X entspricht. ilockann verwendet werden, um die Zeile des DataFrame df für diesen Index abzurufen.

Nafeez Quraishi
quelle
4

Die direkte ".argmax ()" - Lösung funktioniert bei mir nicht.

Das vorherige Beispiel von @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

gibt die folgende Nachricht zurück:

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.

Damit meine Lösung lautet:

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

In dieser einen Codezeile erfahren Sie, wie Sie den Maximalwert aus einer Zeile im Datenrahmen ermitteln. Hier mxist der Datenrahmen und iloc[0]der 0. Index.

Manjula Devi
quelle
1

Der idmaxof the DataFrame gibt den Beschriftungsindex der Zeile mit dem Maximalwert zurück und das Verhalten von argmaxhängt von der Version von ab pandas( im Moment wird eine Warnung zurückgegeben). Wenn Sie den Positionsindex verwenden möchten , können Sie Folgendes tun:

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

oder

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

Beachten Sie, dass sich bei Verwendung np.argmax(df['A'])das gleiche Verhalten verhält wie df['A'].argmax().

Jonathan
quelle