Numpy argsort - apa yang dilakukannya?

123

Mengapa numpy memberikan hasil ini:

x = numpy.array([1.48,1.41,0.0,0.1])
print x.argsort()

>[2 3 1 0]

ketika saya mengharapkannya melakukan ini:

[3 2 0 1]

Jelas pemahaman saya tentang fungsinya kurang.

pengguna1276273
sumber
6
Menurut Anda, mengapa [3 2 0 1]menjadi jawaban yang benar?
zwol
9
Saya baru saja memiliki pemahaman yang terbalik tentang output. Yaitu, jika Anda mengambil elemen pertama dari x, itu harus berada di posisi 3 dari array yang diurutkan dan seterusnya.
pengguna1276273
26
cara berpikir Anda benar-benar masuk akal, saya punya pertanyaan yang persis sama
adrienlucca.wordpress.com
2
[3 2 0 1] - ini adalah peringkat nilai, Anda tidak mendapatkan indeks yang sebenarnya.
Lahiru Karunaratne
Hanya untuk diingat bahwa output menunjukkan lokasi dalam larik asli sementara Anda memikirkannya dalam larik yang diurutkan. Itu berarti keluaran [0] adalah indeks di mana elemen terkecil dalam larik masukan asli ditempatkan dan keluaran [-1] untuk elemen terbesar.
lincr

Jawaban:

143

Menurut dokumentasi

Mengembalikan indeks yang akan mengurutkan larik.

  • 2adalah indeks 0.0.
  • 3adalah indeks 0.1.
  • 1adalah indeks 1.41.
  • 0adalah indeks 1.48.
falsetru.dll
sumber
12
a = x.argsort(), cetak x[a], kita akan mendapatkanarray([ 0. , 0.1 , 1.41, 1.48])
Belter
39

[2, 3, 1, 0] menunjukkan bahwa elemen terkecil ada pada indeks 2, terkecil berikutnya pada indeks 3, kemudian indeks 1, kemudian indeks 0.

Ada beberapa cara untuk mendapatkan hasil yang Anda cari:

import numpy as np
import scipy.stats as stats

def using_indexed_assignment(x):
    "https://stackoverflow.com/a/5284703/190597 (Sven Marnach)"
    result = np.empty(len(x), dtype=int)
    temp = x.argsort()
    result[temp] = np.arange(len(x))
    return result

def using_rankdata(x):
    return stats.rankdata(x)-1

def using_argsort_twice(x):
    "https://stackoverflow.com/a/6266510/190597 (k.rooijers)"
    return np.argsort(np.argsort(x))

def using_digitize(x):
    unique_vals, index = np.unique(x, return_inverse=True)
    return np.digitize(x, bins=unique_vals) - 1

Sebagai contoh,

In [72]: x = np.array([1.48,1.41,0.0,0.1])

In [73]: using_indexed_assignment(x)
Out[73]: array([3, 2, 0, 1])

Ini memeriksa bahwa mereka semua menghasilkan hasil yang sama:

x = np.random.random(10**5)
expected = using_indexed_assignment(x)
for func in (using_argsort_twice, using_digitize, using_rankdata):
    assert np.allclose(expected, func(x))

%timeitTolok ukur IPython ini menyarankan agar array besar using_indexed_assignmentadalah yang tercepat:

In [50]: x = np.random.random(10**5)
In [66]: %timeit using_indexed_assignment(x)
100 loops, best of 3: 9.32 ms per loop

In [70]: %timeit using_rankdata(x)
100 loops, best of 3: 10.6 ms per loop

In [56]: %timeit using_argsort_twice(x)
100 loops, best of 3: 16.2 ms per loop

In [59]: %timeit using_digitize(x)
10 loops, best of 3: 27 ms per loop

Untuk array kecil, using_argsort_twicemungkin lebih cepat:

In [78]: x = np.random.random(10**2)

In [81]: %timeit using_argsort_twice(x)
100000 loops, best of 3: 3.45 µs per loop

In [79]: %timeit using_indexed_assignment(x)
100000 loops, best of 3: 4.78 µs per loop

In [80]: %timeit using_rankdata(x)
100000 loops, best of 3: 19 µs per loop

In [82]: %timeit using_digitize(x)
10000 loops, best of 3: 26.2 µs per loop

Perhatikan juga bahwa stats.rankdatamemberi Anda lebih banyak kontrol atas cara menangani elemen dengan nilai yang sama.

unutbu
sumber
1
Bisakah Anda menambahkan beberapa penjelasan tentang mengapa menerapkan argsort () dua kali memberi kita peringkat?
Phani
1
@Phani: argsortmengembalikan indeks dari array yang diurutkan. Indeks dari indeks yang diurutkan adalah peringkat. Ini adalah panggilan kedua untuk argsortkembali.
unutbu
2
Argsort pertama mengembalikan permutasi (yang jika diterapkan ke data akan mengurutkannya). Ketika argsort diterapkan ke permutasi (ini atau apa pun), ia mengembalikan permutasi terbalik (bahwa jika 2 permutasi diterapkan satu sama lain dalam urutan mana pun hasilnya adalah Identitas). Permutasi kedua jika diterapkan ke larik data yang diurutkan akan menghasilkan larik data yang tidak diurutkan, yaitu peringkat.
Alex C
1
Pikiran meledak. Saya akhirnya mengerti! Ini mengembalikan larik yang isinya adalah indeks dari larik asli dalam urutan yang diurutkan.
Jose A
3

Sebagai dokumentasi mengatakan, argsort:

Mengembalikan indeks yang akan mengurutkan larik.

Artinya elemen pertama dari argsort adalah indeks dari elemen yang harus diurutkan terlebih dahulu, elemen kedua adalah indeks dari elemen yang harus menjadi yang kedua, dll.

Apa yang Anda inginkan adalah urutan peringkat nilai, yang disediakan oleh scipy.stats.rankdata. Perhatikan bahwa Anda perlu memikirkan tentang apa yang harus terjadi jika ada ikatan di peringkat.

BrenBarn
sumber
3

numpy.argsort (a, axis = -1, kind = 'quicksort', order = None)

Mengembalikan indeks yang akan mengurutkan larik

Lakukan pengurutan tidak langsung di sepanjang sumbu yang diberikan menggunakan algoritme yang ditentukan oleh kata kunci kind. Ini mengembalikan array indeks dengan bentuk yang sama seperti data indeks di sepanjang sumbu yang diberikan dalam urutan yang diurutkan.

Pertimbangkan satu contoh di python, memiliki daftar nilai sebagai

listExample  = [0 , 2, 2456,  2000, 5000, 0, 1]

Sekarang kami menggunakan fungsi argsort:

import numpy as np
list(np.argsort(listExample))

Outputnya akan

[0, 5, 6, 1, 3, 2, 4]

Ini adalah daftar indeks nilai di listExample jika Anda memetakan indeks ini ke nilai masing-masing maka kita akan mendapatkan hasilnya sebagai berikut:

[0, 0, 1, 2, 2000, 2456, 5000]

(Saya menemukan fungsi ini sangat berguna di banyak tempat, mis. Jika Anda ingin mengurutkan list / array tetapi tidak ingin menggunakan fungsi list.sort () (yaitu tanpa mengubah urutan nilai aktual dalam daftar) Anda dapat menggunakan ini fungsi.)

Untuk lebih jelasnya lihat tautan ini: https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.argsort.html

Yogesh
sumber
1

masukan:
impor numpy sebagai np
x = np.array ([1.48,1.41,0.0,0.1])
x.argsort (). argsort ()

keluaran:
larik ([3, 2, 0, 1])

JMpony
sumber
1
Meskipun cuplikan kode ini mungkin bisa menjadi solusinya, menyertakan penjelasan sangat membantu untuk meningkatkan kualitas posting Anda. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa mendatang, dan orang-orang itu mungkin tidak tahu alasan saran kode Anda.
peacetype
0

Pertama, itu memerintahkan array. Kemudian buat sebuah array dengan indeks awal dari array tersebut.

Rodrigo Saraguro
sumber
0

np.argsort mengembalikan indeks dari array yang diurutkan yang diberikan oleh 'kind' (yang menentukan tipe algoritma pengurutan). Namun, ketika daftar digunakan dengan np.argmax, ia mengembalikan indeks elemen terbesar dalam daftar. Sementara, np.sort, mengurutkan array yang diberikan, list.

vivek
sumber
0

Hanya ingin secara langsung membandingkan pemahaman asli OP terhadap implementasi aktual dengan kode.

numpy.argsort didefinisikan sedemikian rupa sehingga untuk array 1D:

x[x.argsort()] == numpy.sort(x) # this will be an array of True's

OP awalnya mengira bahwa itu didefinisikan sedemikian rupa untuk array 1D:

x == numpy.sort(x)[x.argsort()] # this will not be True

Catatan: Kode ini tidak berfungsi dalam kasus umum (hanya berfungsi untuk 1D), jawaban ini murni untuk tujuan ilustrasi.

Multihunter
sumber
x[x.argsort()]belum tentu sama dengan np.sort(x). Bahkan, bentuknya belum tentu sama. Coba ini dengan array 2D. Ini hanya terjadi untuk bekerja dengan array 1D.
Nathan
Saya merasa itu terlalu berlebihan. Pertanyaannya adalah tentang array 1D. Ini dimaksudkan sebagai cara untuk memahami apa perbedaannya, bukan kode literal yang digunakan. Selain itu, ketika Anda memiliki array 2D, bahkan tidak jelas pengurutan seperti apa yang Anda inginkan. Apakah Anda menginginkan jenis global? Jika tidak, sumbu mana yang harus diurutkan? Terlepas dari itu, saya telah menambahkan penafian.
Multihunter
0

Ia mengembalikan indeks sesuai dengan indeks array yang diberikan [1.48,1.41,0.0,0.1], itu berarti: 0.0adalah elemen pertama, dalam indeks [2]. 0.1adalah elemen kedua, dalam indeks [3]. 1.41adalah elemen ketiga, dalam indeks [1]. 1.48adalah elemen keempat, dalam indeks [0]. Keluaran:

[2,3,1,0]
nucsit026
sumber