Numpy argsort - ne yapıyor?


123

Numpy neden bu sonucu veriyor:

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

>[2 3 1 0]

bunu yapmasını beklediğimde:

[3 2 0 1]

Açıkçası, işleve ilişkin anlayışım eksik.


6
Neden [3 2 0 1]doğru cevap olacağını düşündün ?
zwol

9
Sadece çıktıyla ilgili ters bir anlayışım vardı. Yani, x'in ilk elemanını alırsanız, sıralı bir dizinin 3. konumunda olması gerekir ve bu böyle devam eder.
user1276273

26
düşünme şekliniz tamamen mantıklı, tam olarak aynı soruyu sormuştum
adrienlucca.wordpress.com

2
[3 2 0 1] - bu, değerleri sıralamaktır, gerçek endeksleri alamıyorsunuz.
Lahiru Karunaratne

Sıralı dizide düşünürken çıktının orijinal dizideki konumları gösterdiğini hatırlamak için. Bu, çıktı [0] 'nın, orijinal girdi dizisindeki en küçük öğenin en büyük öğe için bulduğu ve çıktı [-1] olduğu dizidir.
lincr

Yanıtlar:


144

Belgelere göre

Bir diziyi sıralayacak dizinleri döndürür.

  • 2dizinidir 0.0.
  • 3dizinidir 0.1.
  • 1dizinidir 1.41.
  • 0dizinidir 1.48.

12
a = x.argsort(), yazdır x[a], alacağızarray([ 0. , 0.1 , 1.41, 1.48])
Belter

39

[2, 3, 1, 0] en küçük elemanın dizin 2'de, bir sonraki en küçük elemanın dizin 3'te, sonra dizin 1, sonra dizin 0 olduğunu gösterir.

Orada birçok yolu aradığınız sonuç almak için:

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

Örneğin,

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])

Bu, hepsinin aynı sonucu ürettiğini kontrol eder:

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))

Bu IPython %timeitkarşılaştırmaları, büyük diziler using_indexed_assignmentiçin en hızlı olanıdır :

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

Küçük diziler using_argsort_twiceiçin daha hızlı olabilir:

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

Ayrıca, bunun stats.rankdatasize eşit değere sahip öğelerin nasıl işleneceği konusunda daha fazla kontrol sağladığını unutmayın.


1
Argsort () 'u neden iki kez uygulamanın bize rütbe verdiğine dair biraz açıklama ekleyebilir misiniz?
Phani

1
@Phani: argsortsıralanan dizinin indislerini döndürür. Sıralanan endekslerin dizini sıralamadır. Geri argsortdönmek için ikinci çağrı budur .
unutbu

2
İlk argsort bir permütasyon döndürür (verilere uygulanırsa onu sıralar). Argsort (bu veya herhangi bir) permütasyona uygulandığında, ters permütasyonu döndürür (2 permütasyon birbirine herhangi bir sırayla uygulanırsa sonuç Kimlik olur). İkinci permütasyon, sıralı bir veri dizisine uygulanırsa, sıralanmamış veri dizisini üretecektir, yani bu ranktır.
Alex C

1
Zihin karmaşası. Sonunda anladım! İçeriği orijinal dizinin indisleri olan sıralı bir sırayla bir dizi döndürür.
Jose A

3

Gibi belgeler diyor argsort:

Bir diziyi sıralayacak dizinleri döndürür.

Bu, argsort'un ilk öğesinin, ilk sıralanması gereken öğenin dizini olduğu, ikinci öğenin, ikinci olması gereken öğenin dizin olduğu anlamına gelir.

İstediğiniz gibi görünen şey, değerlerin sıralamasıdır, bu da tarafından sağlanır scipy.stats.rankdata. Saflarda bağlar varsa ne olması gerektiğini düşünmeniz gerektiğini unutmayın.


3

numpy.argsort (a, axis = -1, tür = 'hızlı sıralama', sıra = Yok)

Bir diziyi sıralayacak indisleri verir

Kind anahtar sözcüğü ile belirtilen algoritmayı kullanarak verilen eksen boyunca dolaylı bir sıralama gerçekleştirin. Belirtilen eksen boyunca sıralı bir şekilde, dizin verileriyle aynı şekle sahip bir dizi dizin döndürür.

Bir değer listesi olan python'da bir örnek düşünün.

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

Şimdi argsort işlevini kullanıyoruz:

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

Çıktı olacak

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

Bu, listExample'daki değerlerin indekslerinin listesidir. Bu indisleri ilgili değerlerle eşlerseniz, sonucu şu şekilde alacağız:

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

(Bu işlevi pek çok yerde çok yararlı buluyorum, örneğin, liste / diziyi sıralamak istiyor ancak list.sort () işlevini kullanmak istemiyorsanız (yani listedeki gerçek değerlerin sırasını değiştirmeden) bunu kullanabilirsiniz. işlev.)

Daha fazla ayrıntı için şu bağlantıya bakın: https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.argsort.html


1

input:
np
x = np.array ([1.48,1.41,0.0,0.1])
x.argsort (). argsort () olarak numpy içe aktar

çıktı:
dizi ([3, 2, 0, 1])


1
Bu kod parçacığı çözüm olabilir, ancak bir açıklama da dahil olmak üzere yayınınızın kalitesini artırmaya gerçekten yardımcı olur. Gelecekte okuyucular için soruyu yanıtladığınızı ve bu kişilerin kod önerinizin nedenlerini bilmeyebileceklerini unutmayın.
peacetype

0

İlk olarak, dizi sipariş edildi. Ardından, dizinin ilk diziniyle bir dizi oluşturun.


0

np.argsort, 'tür' (sıralama algoritmasının türünü belirten) tarafından verilen sıralanmış dizinin dizinini döndürür. Bununla birlikte, bir liste np.argmax ile kullanıldığında, listedeki en büyük elemanın dizinini döndürür. Np.sort, verilen diziyi listeler.


0

Sadece OP'nin orijinal anlayışını gerçek uygulama ile kod ile doğrudan karşılaştırmak istiyorum.

numpy.argsort 1 boyutlu diziler için:

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

OP başlangıçta 1D dizileri için şu şekilde tanımlandığını düşündü:

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

Not: Bu kod genel durumda çalışmaz (yalnızca 1D için çalışır), bu yanıt tamamen örnekleme amaçlıdır.


x[x.argsort()]ile aynı olmak zorunda değildir np.sort(x). Aslında, aynı şekilde olması bile gerekmez. Bunu bir 2B diziyle deneyin. Bu yalnızca 1D dizilerle çalışır.
Nathan

Bunun gereksiz bir bilgiçlik olduğunu düşünüyorum. Soru 1B dizilerle ilgili. Bu, kullanılacak gerçek koddan ziyade farkın ne olduğunu anlamanın bir yolu olarak tasarlanmıştır. Ek olarak, bir 2D diziniz olduğunda, ne tür bir sıralama istediğinizi bile bilmiyorsunuz. Küresel bir sıralama ister misiniz? Değilse, hangi eksen sıralanmalıdır? Ne olursa olsun, bir sorumluluk reddi beyanı ekledim.
Multihunter

0

Verilen dizi indekslerine göre indisleri döndürür [1.48,1.41,0.0,0.1], bunun anlamı: 0.0indeks [2] 'deki ilk elemandır. 0.1[3] dizinindeki ikinci öğedir. 1.41[1] dizinindeki üçüncü öğedir. 1.48[0] dizinindeki dördüncü öğedir. Çıktı:

[2,3,1,0]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.