NumPy mengusulkan cara untuk mendapatkan indeks dari nilai maksimum sebuah array via np.argmax
.
Saya ingin hal serupa, tetapi mengembalikan indeks dari nilai N
maksimum.
Misalnya, jika saya memiliki array [1, 3, 2, 4, 5]
,, function(array, n=3)
akan mengembalikan indeks [4, 3, 1]
yang sesuai dengan elemen [5, 4, 3]
.
python
numpy
max
numpy-ndarray
Alexis Métaireau
sumber
sumber
array([5, 1, 5, 5, 2, 3, 2, 4, 1, 5])
, sedikit punn= 3
? Yang mana semua alternatif, seperti[0, 2, 3]
,[0, 2, 9]
,...
akan menjadi salah satu yang benar? Silakan uraikan lebih lanjut tentang persyaratan spesifik Anda. Terima kasihargsort
mungkin menjadi alternatif yang layak jika Anda tidak peduli dengan urutan indeces yang dikembalikan. Lihat jawaban saya di bawah ini.Jawaban:
Yang paling sederhana yang bisa saya lakukan adalah:
Ini melibatkan semacam array lengkap. Saya ingin tahu apakah
numpy
menyediakan cara bawaan untuk melakukan semacam parsial; sejauh ini saya belum dapat menemukannya.Jika solusi ini ternyata terlalu lambat (terutama untuk yang kecil
n
), mungkin perlu melihat pengkodean sesuatu di Cython .sumber
arr.argsort()[-1:-4:-1]
? Saya sudah mencobanya dalam penerjemah dan muncul dengan hasil yang sama, tapi saya bertanya-tanya apakah itu tidak rusak oleh beberapa contoh.np.argsort(-arr)[:3]
, yang menurut saya lebih mudah dibaca dan to the point.arr.argsort()[::-1][:n]
lebih baik karena mengembalikan kosong untukn=0
bukan array penuhVersi NumPy yang lebih baru (1,8 dan lebih tinggi) memiliki fungsi yang disebut
argpartition
untuk ini. Untuk mendapatkan indeks dari empat elemen terbesar, lakukanTidak seperti
argsort
, fungsi ini berjalan dalam waktu linier dalam kasus terburuk, tetapi indeks yang dikembalikan tidak diurutkan, seperti yang dapat dilihat dari hasil evaluasia[ind]
. Jika Anda juga membutuhkannya, urutkan setelahnya:Untuk mendapatkan elemen topk dalam urutan diurutkan dengan cara ini membutuhkan waktu O ( n + k log k ).
sumber
argpartition
berjalan dalam waktu linier, O (n), menggunakan algoritma introselect . Urutan berikutnya hanya menangani elemen k, sehingga berjalan di O (k log k).np.argpartition
dan algoritma saudaranp.partition
bekerja, ada penjelasan yang lebih rinci dalam pertanyaan terkait: stackoverflow.com/questions/10337533/...a=np.array([9, 4, 4, 3, 3, 9, 0, 4, 6, 0])
karena daftar python normal tidak mendukung pengindeksan berdasarkan daftar, tidak sepertinp.array
np.argpartition
mengambilaxis
argumen opsional . Untuk menemukan indeks nilai n teratas untuk setiap baris:np.argpartition(a, -n, axis=1)[-n:]
Lebih sederhana:
di mana n adalah jumlah nilai maksimum.
sumber
arr[arr.argsort()[-n:]]
bukannya meniadakan array, hanya mengambil sepotong elemen n terakhirMenggunakan:
Untuk daftar Python biasa:
Jika Anda menggunakan Python 2, gunakan
xrange
sebagai gantirange
.Sumber: heapq - Heap queue algorithm
sumber
heapq.nlargest(3, xrange(len(a)), a.take)
. Untuk daftar Python, kita bisa menggunakan.__getitem__
bukan.take
.A
pada umumnya:heapq.nlargest(3, range(len(A.ravel())), A.ravel().take)
. (Saya harap ini hanya beroperasi pada tampilan, lihat juga (ravel vs flatten
] ( stackoverflow.com/a/28930580/603003 ))Jika Anda kebetulan menggunakan array multidimensi maka Anda harus meratakan dan mengurai indeks:
Sebagai contoh:
sumber
Jika Anda tidak peduli dengan urutan elemen terbesar K-th yang dapat Anda gunakan
argpartition
, yang seharusnya berkinerja lebih baik daripada memilah secara lengkapargsort
.Kredit pergi ke pertanyaan ini .
Saya menjalankan beberapa tes dan sepertinya
argpartition
mengungguliargsort
ukuran array dan nilai K meningkat.sumber
Untuk array multidimensi Anda dapat menggunakan
axis
kata kunci untuk menerapkan partisi di sepanjang sumbu yang diharapkan.Dan untuk mengambil item:
Tetapi perhatikan bahwa ini tidak akan mengembalikan hasil yang diurutkan. Dalam hal ini Anda dapat menggunakan
np.argsort()
sepanjang sumbu yang dimaksud:Berikut ini sebuah contoh:
sumber
np.take_along_axis
(yang kemungkinan tidak ada ketika Anda menjawab pertanyaan ini)Ini akan lebih cepat daripada penyortiran penuh tergantung pada ukuran array asli Anda dan ukuran pilihan Anda:
Ini, tentu saja, melibatkan pengubahan array asli Anda. Yang dapat Anda perbaiki (jika perlu) dengan membuat salinan atau mengganti kembali nilai-nilai aslinya. ... mana yang lebih murah untuk kasus penggunaan Anda.
sumber
argmax(.)
tidak ambigu juga. (IMHO ia mencoba mengikuti semacam logika hubungan pendek, tetapi sayangnya gagal memberikan perilaku yang dapat diterima secara universal). Terima kasihMetode
np.argpartition
hanya mengembalikan indeks terbesar k, melakukan pengurutan lokal, dan lebih cepat daripadanp.argsort
(melakukan pengurutan penuh) ketika array cukup besar. Tetapi indeks yang dikembalikan TIDAK dalam urutan naik / turun . Katakanlah dengan sebuah contoh:Kita dapat melihat bahwa jika Anda menginginkan indeks top k pesanan naik yang ketat,
np.argpartition
tidak akan mengembalikan apa yang Anda inginkan.Selain melakukan pengurutan secara manual setelah np.argpartition, solusi saya adalah menggunakan PyTorch,,
torch.topk
alat untuk konstruksi jaringan saraf, menyediakan API mirip NumPy dengan dukungan CPU dan GPU. Ini secepat NumPy dengan MKL, dan menawarkan peningkatan GPU jika Anda membutuhkan perhitungan matriks / vektor yang besar.Kode indeks kenaikan ascend / descend ketat adalah:
Perhatikan bahwa
torch.topk
menerima tensor obor, dan mengembalikan kedua nilai k atas dan indeks k atas dalam jenistorch.Tensor
. Mirip dengan np, torch.topk juga menerima argumen sumbu sehingga Anda dapat menangani array / tensor multi-dimensi.sumber
Menggunakan:
Sekarang
result
daftar akan berisi N tupel (index
,value
) di manavalue
dimaksimalkan.sumber
Menggunakan:
Ini juga bekerja dengan array 2D. Sebagai contoh,
sumber
bottleneck
memiliki fungsi sortir parsial, jika biaya memilah seluruh array hanya untuk mendapatkan nilai N terbesar terlalu besar.Saya tidak tahu apa-apa tentang modul ini; Saya baru saja googled
numpy partial sort
.sumber
Berikut ini adalah cara yang sangat mudah untuk melihat elemen maksimum dan posisinya. Ini
axis
domainnya;axis
= 0 berarti jumlah maksimum bijaksana kolom danaxis
= 1 berarti jumlah maksimum baris bijaksana untuk kasus 2D. Dan untuk dimensi yang lebih tinggi itu tergantung pada Anda.sumber
Saya menemukan ini paling intuitif untuk digunakan
np.unique
.Idenya adalah, bahwa metode unik mengembalikan indeks nilai input. Kemudian dari nilai unik maks dan indeks, posisi nilai asli dapat dibuat kembali.
sumber
Saya pikir cara efisiensi waktu yang paling banyak adalah secara manual beralih melalui array dan menyimpan min-heap k-size, seperti yang orang lain katakan.
Dan saya juga datang dengan pendekatan brute force:
Atur elemen terbesar ke nilai negatif besar setelah Anda menggunakan argmax untuk mendapatkan indeksnya. Dan kemudian panggilan argmax selanjutnya akan mengembalikan elemen terbesar kedua. Dan Anda dapat mencatat nilai asli dari elemen-elemen ini dan memulihkannya jika Anda mau.
sumber
Kode ini berfungsi untuk array matriks numpy:
Ini menghasilkan pengindeksan matriks n_largest true-false yang juga berfungsi untuk mengekstrak elemen n_largest dari array matriks
sumber