Znajdź wiersz, w którym wartości kolumny są maksymalne w ramce DataFrame pandy

208

Jak znaleźć wiersz, dla którego wartość konkretnej kolumny jest maksymalna ?

df.max() da mi maksymalną wartość dla każdej kolumny, nie wiem jak uzyskać odpowiedni wiersz.

leniwy 1
źródło
Czy można uzyskać 2 najwyższe wartości? zamiast tylko maksimum?
AsheKetchum
5
Możesz użyć sort_valuesi uzyskać indeks:df.sort_values('col', ascending=False)[:2].index
lazy1
2
lazy1: unikaj niepotrzebnego sortowania całej serii, ponieważ średnio jest to O (N logN), podczas gdy znalezienie max / idxmax to tylko O ​​(N).
smci

Odpowiedzi:

240

Użyj idxmaxfunkcji pandy . To proste:

>>> 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
  • Alternatywnie możesz również użyć numpy.argmax, na przykład numpy.argmax(df['A'])- zapewnia to samo i pojawia się co najmniej tak szybko, jak idxmaxw pobieżnych obserwacjach.

  • idxmax() zwraca etykiety indeksów, a nie liczby całkowite.

    • Przykład: jeśli masz wartości ciągu jako etykiety indeksu, takie jak wiersze od „a” do „e”, możesz chcieć wiedzieć, że maksimum występuje w wierszu 4 (nie w wierszu „d”).
    • jeśli chcesz, aby liczba całkowita tej etykiety była wewnątrz Index, musisz uzyskać ją ręcznie (co może być trudne, ponieważ dozwolone są duplikaty etykiet wierszy).

UWAGI HISTORYCZNE:

  • idxmax()był wywoływany argmax()przed 0.11
  • argmax był przestarzały przed wersją 1.0.0 i całkowicie usunięty w wersji 1.0.0
  • z powrotem od wersji Panda 0.16, argmaxkiedyś istniał i pełnił tę samą funkcję (choć wydawał się działać wolniej niż idxmax).
    • argmaxfunkcja zwróciła pozycję całkowitą w indeksie położenia wiersza maksymalnego elementu.
    • pandy przeniesiono do używania etykiet wierszy zamiast indeksów całkowitych. Wskaźniki liczb całkowitych pozycyjnych były kiedyś bardzo powszechne, częściej niż etykiety, szczególnie w aplikacjach, w których zduplikowane etykiety wierszy są wspólne.

Na przykład rozważ tę zabawkę DataFrameze zduplikowaną etykietą wiersza:

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

Zatem naiwne użycie idxmaxnie jest wystarczające, podczas gdy stara forma argmaxpoprawnie zapewniałaby położenie pozycyjne rzędu maksymalnego (w tym przypadku pozycja 9).

Jest to dokładnie jedno z tych paskudnych rodzajów podatnych na błędy zachowań w dynamicznie pisanych językach, które sprawiają, że takie rzeczy są tak niefortunne i warte pokonania martwego konia. Jeśli piszesz kod systemu, a Twój system nagle przyzwyczaja się do niektórych zestawów danych, które nie są odpowiednio czyszczone przed dołączeniem, bardzo łatwo jest uzyskać zduplikowane etykiety wierszy, zwłaszcza etykiety ciągów, takie jak identyfikator CUSIP lub SEDOL dla aktywów finansowych. Nie możesz łatwo użyć systemu typów, aby ci pomóc, i możesz nie być w stanie wymusić wyjątkowości indeksu bez napotkania nieoczekiwanie brakujących danych.

Pozostaje ci więc nadzieja, że ​​twoje testy jednostkowe obejmują wszystko (one nie, lub bardziej prawdopodobne, że nikt nie napisał żadnych testów) - w przeciwnym razie (najprawdopodobniej) po prostu czekasz, czy zdarzy ci się w to uderzyć błąd w czasie wykonywania, w którym to przypadku prawdopodobnie musisz rzucić wiele godzin pracy z bazy danych, do której wypisywałeś wyniki, uderz głową o ścianę w IPython, próbując ręcznie odtworzyć problem, w końcu stwierdzając, że to dlatego, że idxmaxmożna tylko zgłoś etykietę maksymalnego wiersza, a następnie rozczarowany, że żadna standardowa funkcja nie pobiera automatycznie pozycji maksymalnego wiersza, samodzielnie pisząc błędną implementację, edytując kod i modląc się, abyś nie napotkał ponownie problemu.

Ely
źródło
13
Oparty na przedostatnim komentarzu wygląda argmini argmaxpozostanie częścią, DataFramea różnica polega tylko na tym, czy chcesz indeks, czy etykietę. idxmaxpoda etykietę lokalizacji, w której występuje maksimum. argmaxda ci liczbę całkowitą indeksu.
ely
4
Informacje podane w celu wyjaśnienia różnicy między argmaxi idxmaxoraz w jaki sposób uniknąć błędów ze zduplikowanym indeksem były świetne! Nie zauważyłem tego, dopóki nie przeczytałem twojego komentarza w drugiej odpowiedzi. Dzięki!
tupan
W odniesieniu do zastosowania, które chcesz wdrożyć, Pandas 0.24.1 wskazuje na następujące: „zachowanie argmaxzostanie poprawione, aby przywrócić maksimum pozycji w przyszłości. Na razie użyj series.values.argmaxlub, np.argmax(np.array(values))aby uzyskać pozycję maksymalnego rzędu. ”
Sam
1
podobnie .ixzmieniono nazwę metody z drugiego przykładu na.iloc
Ma0,
jeśli twoja kolumna zawiera tylko wartości nan, spowoduje to TypeError
Max Segal
77

Możesz także spróbować 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

na przykład

In [8]: df.loc[df['A'].idxmax()]
Out[8]: 
A    2.001289
B    0.482561
C    1.579985
Wes McKinney
źródło
Dzięki Wes. Dokumentacja dla idxmax () tutaj: pandas.pydata.org/pandas-docs/dev/generated/…
Czy
df.ix[df['A'].idxmax()].valuesaby złapać tablicę, którą chciałem. nadal działa.
Yojimbo,
2
Pamiętaj, że musisz zachować ostrożność, próbując wykorzystać dane wyjściowe idxmaxjako podajnik do ixlub locjako środek do podzielenia danych na części i / lub uzyskania położenia pozycyjnego maksymalnego wiersza. Ponieważ możesz mieć duplikaty w Index- patrz aktualizacja mojej odpowiedzi na przykład.
ely
25

Obie powyższe odpowiedzi zwrócą tylko jeden indeks, jeśli istnieje wiele wierszy, które przyjmują maksymalną wartość. Jeśli chcesz wszystkie wiersze, nie ma funkcji. Ale nie jest to trudne. Poniżej znajduje się przykład dla Series; to samo można zrobić dla 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
źródło
10
Dzięki! wersja dla DataFrame:df[df['A'] == df['A'].max()]
Dennis Golomazov
To jest właściwie poprawna odpowiedź (wersja DataFrame).
gented
12
df.iloc[df['columnX'].argmax()]

argmax()podałby indeks odpowiadający maksymalnej wartości dla kolumnyX. ilocmożna użyć, aby uzyskać wiersz DataFrame df dla tego indeksu.

Nafeez Quraishi
źródło
4

Bezpośrednie rozwiązanie „.argmax ()” nie działa dla mnie.

Poprzedni przykład podany przez @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

zwraca następujący komunikat:

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.

Tak więc moim rozwiązaniem jest:

df['A'].values.argmax()
AntoineP
źródło
2
mx.iloc[0].idxmax()

Ten jeden wiersz kodu pokaże ci, jak znaleźć maksymalną wartość z wiersza w ramce danych, tutaj mxjest ramka danych i iloc[0]wskazuje zerowy indeks.

Manjula Devi
źródło
1

Funkcja idmaxDataFrame zwraca indeks etykiety wiersza z maksymalną wartością, a zachowanie argmaxzależy od wersji pandas(w tej chwili zwraca ostrzeżenie). Jeśli chcesz użyć indeksu pozycyjnego , możesz wykonać następujące czynności:

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

lub

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

Pamiętaj, że jeśli używasz np.argmax(df['A'])zachowuje się tak samo jak df['A'].argmax().

Jonathan
źródło