Temukan baris di mana nilai untuk kolom maksimal dalam panda DataFrame

209

Bagaimana saya bisa menemukan baris yang nilai kolom tertentunya maksimal ?

df.max() akan memberi saya nilai maksimal untuk setiap kolom, saya tidak tahu cara mendapatkan baris yang sesuai.

lazy1
sumber
Apakah mungkin untuk mendapatkan nilai 2 teratas? bukan hanya maks?
AsheKetchum
5
Anda dapat menggunakan sort_valuesdan mendapatkan indeks:df.sort_values('col', ascending=False)[:2].index
lazy1
2
lazy1: hindari menyortir seluruh rangkaian yang tidak perlu karena rata-rata adalah O (N logN), sedangkan menemukan max / idxmax hanya O (N).
smci

Jawaban:

240

Gunakan idxmaxfungsi panda . Sangat mudah:

>>> 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
  • Atau Anda juga bisa menggunakan numpy.argmax, seperti numpy.argmax(df['A'])- ia menyediakan hal yang sama, dan muncul setidaknya secepatidxmax dalam pengamatan sepintas.

  • idxmax() mengembalikan label indeks, bukan bilangan bulat.

    • Contoh ': jika Anda memiliki nilai string sebagai label indeks Anda, seperti baris' a 'hingga' e ', Anda mungkin ingin tahu bahwa max muncul di baris 4 (bukan baris' d ').
    • jika Anda ingin posisi integer dari label di dalam IndexAnda harus mendapatkannya secara manual (yang bisa rumit sekarang karena label baris duplikat diperbolehkan).

CATATAN SEJARAH:

  • idxmax()dulu dipanggil argmax()sebelum 0,11
  • argmax dihentikan sebelum 1.0.0 dan dihapus seluruhnya pada 1.0.0
  • kembali pada Pandas 0.16, argmaxdulu ada dan melakukan fungsi yang sama (meskipun tampaknya berjalan lebih lambat dari idxmax).
    • argmaxfungsi mengembalikan posisi integer dalam indeks lokasi baris elemen maksimum.
    • panda dipindahkan menggunakan label baris alih-alih indeks integer. Indeks integer posisi dulu sangat umum, lebih umum daripada label, terutama dalam aplikasi di mana label baris duplikat umum.

Misalnya, pertimbangkan mainan ini DataFramedengan label baris duplikat:

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

Jadi di sini penggunaan naif idxmaxtidak cukup, sedangkan bentuk lama argmaxakan dengan benar memberikan lokasi posisi baris maks (dalam hal ini, posisi 9).

Ini persis salah satu dari jenis perilaku rawan bug dalam bahasa yang diketik secara dinamis yang membuat hal semacam ini sangat disayangkan, dan layak mengalahkan kuda mati. Jika Anda menulis kode sistem dan sistem Anda tiba-tiba digunakan pada beberapa set data yang tidak dibersihkan dengan benar sebelum bergabung, sangat mudah untuk berakhir dengan label baris duplikat, terutama label string seperti pengidentifikasi CUSIP atau SEDOL untuk aset keuangan. Anda tidak dapat dengan mudah menggunakan sistem tipe untuk membantu Anda, dan Anda mungkin tidak dapat menegakkan keunikan pada indeks tanpa mengalami data yang hilang secara tak terduga.

Jadi Anda pergi dengan harapan bahwa unit test Anda mencakup semuanya (tidak, atau lebih mungkin tidak ada yang menulis tes) - jika tidak (kemungkinan besar) Anda hanya menunggu untuk melihat apakah Anda kebetulan menabrak ini kesalahan saat runtime, dalam hal ini Anda mungkin harus bekerja berjam-jam dari database yang Anda hasilkan hasilnya, membenturkan kepala Anda ke dinding di IPython mencoba mereproduksi masalah secara manual, akhirnya mencari tahu bahwa itu karena hanyaidxmax bisa laporkan label baris maks, dan kemudian kecewa karena tidak ada fungsi standar yang secara otomatis mendapatkan posisi baris max untuk Anda, menulis sendiri implementasi kereta, mengedit kode, dan berdoa Anda tidak mengalami masalah lagi.

Ely
sumber
13
Berdasarkan komentar kedua hingga terakhir di sana, sepertinya argmindan argmaxakan tetap menjadi bagian DataFramedan perbedaannya hanya apakah Anda ingin indeks atau label. idxmaxakan memberi Anda label lokasi tempat max terjadi. argmaxakan memberi Anda bilangan bulat indeks itu sendiri.
ely
4
Informasi yang diberikan untuk menjelaskan perbedaan antara argmaxdan idxmax, dan bagaimana cara menghindari bug dengan indeks yang digandakan itu hebat! Saya belum menyadarinya sampai saya membaca komentar Anda di jawaban yang lain. Terima kasih!
tupan
Mengenai penggunaan yang ingin Anda terapkan, Pandas 0.24.1 menunjukkan hal-hal berikut: 'perilaku argmaxakan diperbaiki untuk mengembalikan posisi maksimum di masa mendatang. Untuk saat ini, gunakan series.values.argmaxatau np.argmax(np.array(values))untuk mendapatkan posisi baris maksimum. '
Sam
1
sama halnya, .ixmetode dari contoh kedua telah diubah namanya menjadi.iloc
Ma0
jika kolom Anda hanya berisi nilai nan, ini akan menghasilkan TypeError
Max Segal
77

Anda mungkin juga mencoba 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

misalnya

In [8]: df.loc[df['A'].idxmax()]
Out[8]: 
A    2.001289
B    0.482561
C    1.579985
Wes McKinney
sumber
Terima kasih Wes. Dokumentasi untuk idxmax () di sini: pandas.pydata.org/pandas-docs/dev/generated/…
Will
df.ix[df['A'].idxmax()].valuesuntuk mengambil array yang saya inginkan. masih bekerja.
Yojimbo
2
Perhatikan bahwa Anda harus berhati-hati mencoba menggunakan output idxmaxsebagai feeder ke ixatau locsebagai sarana untuk mengelompokkan data dan / atau untuk mendapatkan lokasi posisi baris-maksimum. Karena Anda dapat memiliki duplikat di Index- lihat pembaruan untuk jawaban saya sebagai contoh.
ely
25

Kedua jawaban di atas hanya akan mengembalikan satu indeks jika ada beberapa baris yang mengambil nilai maksimum. Jika Anda ingin semua baris, tampaknya tidak memiliki fungsi. Tetapi itu tidak sulit untuk dilakukan. Di bawah ini adalah contoh untuk Seri; hal yang sama dapat dilakukan untuk 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
sumber
10
Terima kasih! versi untuk DataFrame:df[df['A'] == df['A'].max()]
Dennis Golomazov
Ini adalah jawaban yang benar-benar benar (versi DataFrame).
gented
12
df.iloc[df['columnX'].argmax()]

argmax()akan memberikan indeks yang sesuai dengan nilai maksimum untuk kolomX. ilocdapat digunakan untuk mendapatkan baris DataFrame df untuk indeks ini.

Nafeez Quraishi
sumber
4

Solusi ".argmax ()" langsung tidak bekerja untuk saya.

Contoh sebelumnya disediakan oleh @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

mengembalikan pesan berikut:

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.

Sehingga solusi saya adalah:

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

Satu baris kode ini akan memberi Anda cara menemukan nilai maksimum dari satu baris dalam kerangka data, di sini mxkerangka data dan iloc[0]menunjukkan indeks ke-0.

Manjula Devi
sumber
1

The idmaxdari DataFrame mengembalikan indeks label baris dengan nilai maksimum dan perilaku argmaxtergantung pada versi pandas(sekarang ia mengembalikan peringatan). Jika Anda ingin menggunakan indeks posisi , Anda dapat melakukan hal berikut:

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

atau

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

Perhatikan bahwa jika Anda menggunakan np.argmax(df['A'])berperilaku sama dengan df['A'].argmax().

Jonathan
sumber