Saya memiliki array angka dan saya ingin membuat array lain yang mewakili peringkat setiap item di array pertama. Saya menggunakan Python dan NumPy.
Sebagai contoh:
array = [4,2,7,1]
ranks = [2,1,3,0]
Inilah metode terbaik yang saya dapatkan:
array = numpy.array([4,2,7,1])
temp = array.argsort()
ranks = numpy.arange(len(array))[temp.argsort()]
Apakah ada metode yang lebih baik / lebih cepat yang menghindari pengurutan array dua kali?
ranks = temp.argsort()
.Jawaban:
Gunakan pengiris di sisi kiri pada langkah terakhir:
Ini menghindari pengurutan dua kali dengan membalik permutasi pada langkah terakhir.
sumber
Gunakan argsort dua kali, pertama untuk mendapatkan urutan larik, lalu untuk mendapatkan peringkat:
Saat berhadapan dengan array 2D (atau dimensi yang lebih tinggi), pastikan untuk memberikan argumen sumbu ke argsort untuk diurutkan di atas sumbu yang benar.
sumber
[4,2,7,1,1]
), keluaran akan memberi peringkat nomor tersebut berdasarkan posisi[3,2,4,0,1]
argsort
.array = np.random.rand(10)
seharusnyaarray = np.random.rand(n)
.Pertanyaan ini sudah berumur beberapa tahun, dan jawaban yang diterima bagus, tetapi saya pikir yang berikut ini masih layak untuk disebutkan. Jika Anda tidak keberatan dengan ketergantungan ini
scipy
, Anda dapat menggunakanscipy.stats.rankdata
:Fitur yang bagus
rankdata
adalah bahwamethod
argumen menyediakan beberapa opsi untuk menangani hubungan. Misalnya, ada tiga kemunculan 20 dan dua kemunculan 40 dib
:Default memberikan peringkat rata-rata ke nilai terikat:
method='ordinal'
memberikan peringkat berturut-turut:method='min'
memberikan peringkat minimum dari nilai terikat ke semua nilai terikat:Lihat docstring untuk opsi lebih lanjut.
sumber
rankdata
tampaknya menggunakan mekanisme yang sama dengan jawaban yang diterima untuk menghasilkan peringkat awal secara internal.Saya mencoba memperluas kedua solusi untuk array A lebih dari satu dimensi, misalkan Anda memproses array baris demi baris (axis = 1).
Saya memperpanjang kode pertama dengan loop pada baris; mungkin itu bisa diperbaiki
Dan yang kedua, mengikuti saran k.rooijers, menjadi:
Saya secara acak menghasilkan 400 array dengan bentuk (1000,100); kode pertama membutuhkan waktu sekitar 7,5, yang kedua 3,8.
sumber
Untuk versi vektor dari peringkat rata-rata, lihat di bawah. Saya suka np.unique, ini benar-benar memperluas cakupan kode apa yang dapat dan tidak dapat di-vektorisasi secara efisien. Selain menghindari loop-for python, pendekatan ini juga menghindari loop ganda implisit di atas 'a'.
sumber
Terlepas dari keanggunan dan singkatnya solusi, ada juga pertanyaan tentang kinerja. Ini sedikit patokannya:
sumber
rankdata(l, method='ordinal') - 1
.Gunakan argsort () dua kali akan melakukannya:
sumber
Saya mencoba metode di atas, tetapi gagal karena saya memiliki banyak zeores. Ya, bahkan dengan float barang duplikat mungkin penting.
Jadi saya menulis solusi 1D yang dimodifikasi dengan menambahkan langkah pemeriksaan dasi:
Saya percaya ini seefisien mungkin.
sumber
Saya menyukai metode oleh k.rooijers, tetapi seperti yang ditulis rcoup, angka yang diulang diberi peringkat sesuai dengan posisi array. Ini tidak baik bagi saya, jadi saya memodifikasi versinya untuk memproses peringkat dan menggabungkan angka berulang apa pun menjadi peringkat rata-rata gabungan:
Saya harap ini dapat membantu orang lain juga, saya mencoba menemukan solusi lain untuk ini, tetapi tidak dapat menemukan ...
sumber
argsort dan slice adalah operasi simetri.
coba iris dua kali, bukan argsort dua kali. karena slice lebih cepat dari argsort
sumber
Versi yang lebih umum dari salah satu jawaban:
Lihat Bagaimana cara menggunakan numpy.argsort () sebagai indeks di lebih dari 2 dimensi? untuk menggeneralisasi menjadi lebih redup.
sumber