Uyuşmuş bir diziyi azalan sırada verimli bir şekilde sıralıyor musunuz?


121

Bu özel sorunun daha önce sorulmamış olmasına şaşırdım, ancak gerçekten SO'da veya belgelerinde bulamadım np.sort.

Tam sayıları tutan rastgele bir uyuşuk dizim olduğunu varsayalım, örneğin:

> temp = np.random.randint(1,10, 10)    
> temp
array([2, 4, 7, 4, 2, 2, 7, 6, 4, 4])

Sıralarsam, varsayılan olarak artan düzen elde ederim:

> np.sort(temp)
array([2, 2, 2, 4, 4, 4, 4, 6, 7, 7])

ancak çözümün azalan sırada sıralanmasını istiyorum .

Şimdi, her zaman yapabileceğimi biliyorum:

reverse_order = np.sort(temp)[::-1]

ama bu son ifade etkili mi? Artan sırada bir kopya oluşturmaz ve ardından sonucu ters sırayla almak için bu kopyayı tersine çevirmez mi? Durum gerçekten böyleyse, etkili bir alternatif var mı? np.sortİşleri ters sırayla almak için sıralama işleminde karşılaştırmaların işaretini değiştirmek için parametreleri kabul ediyor gibi görünmüyor .

Yanıtlar:


139

temp[::-1].sort()diziyi yerinde sıralar, np.sort(temp)[::-1]yeni bir dizi oluşturur.

In [25]: temp = np.random.randint(1,10, 10)

In [26]: temp
Out[26]: array([5, 2, 7, 4, 4, 2, 8, 6, 4, 4])

In [27]: id(temp)
Out[27]: 139962713524944

In [28]: temp[::-1].sort()

In [29]: temp
Out[29]: array([8, 7, 6, 5, 4, 4, 4, 4, 2, 2])

In [30]: id(temp)
Out[30]: 139962713524944

30
Teşekkürler, ama temp[::-1].sort()ters sırayla sıralaması gerektiğini nereden biliyor? Onu okuma şeklim şu: orijinal diziyi tersine çevirin ve sonra sıralayın (artan sırada). Orijinal diziyi ters çevirmek (rastgele sırayla gelir) ve ardından artan sırada sıralamak, diziyi ters sırayla döndürür?
Amelio Vazquez-Reina

14
Bu davranış, oldukça sezgisel olmadığı için belgelenmiş mi?
ebarr

18
Bu işe yarıyor gibi görünüyor çünkü [::-1]numpy'ye diziyi gerçekten yeniden sıralamaktan ziyade dizi üzerinde geriye doğru yineleme yapmasını söylüyor. Yani yerinde sıralama gerçekleştiğinde, aslında artan sırada sıralar ve bitleri hareket ettirir, ancak geriye doğru yineleme kısmını el değmeden bırakır.
perimosocordiae

46
İle a=np.array((...))deyim a[::-1]şey ters gelmez, sadece var yeni görünümü aynı verilere, daha spesifik bir ayna görünümü. Yöntem a[::-1].sort() aynalı görüntü üzerinde çalışır ve aynalanmış görüntüsünde daha küçük bir öğeyi solasort hareket ettirdiğinde , gerçekte onu dizinin gerçek bellek bloğunda sağa hareket ettirdiğini ima eder . Yansıtılmış görünüm artan sırada sıralanır, gerçek veriler azalan sırada sıralanır. Birkaç farklı bozuk para ve bir ayna ile evde kendiniz deneyin! a
gboffi

30
Bu np.sort(temp,order='descending')tür saldırıları gerektirmek yerine , bu gerçekten okunabilir bir parametre olarak eklenmelidir
Nathan

92
>>> a=np.array([5, 2, 7, 4, 4, 2, 8, 6, 4, 4])

>>> np.sort(a)
array([2, 2, 4, 4, 4, 4, 5, 6, 7, 8])

>>> -np.sort(-a)
array([8, 7, 6, 5, 4, 4, 4, 4, 2, 2])

2
En iyi cevap - kısa ve tatlı ve hiçbir bilginin axishangi np.sortuygulandı gereklidir.
Luke Davis

2
Bu, dizinin ön yerine arka tarafına np.sort(temp)[::-1]yerleştirilmesinden farklıdır nan. İyi ya da kötü olsun tartışmaya açıktır ..
Ben

15

Kısa diziler için np.argsort(), sıralı diziyi tersine çevirmekten biraz daha hızlı olan, sıralı negatif dizinin dizinlerini bularak kullanmanızı öneririm :

In [37]: temp = np.random.randint(1,10, 10)

In [38]: %timeit np.sort(temp)[::-1]
100000 loops, best of 3: 4.65 µs per loop

In [39]: %timeit temp[np.argsort(-temp)]
100000 loops, best of 3: 3.91 µs per loop

a[np.argsort(-a)]muhtemelen bu sayfadaki diğerlerine en iyi yaklaşımdır. -1 adım tersine çevirme yok ve üzerinde düşünmek için bir eksi işareti yok.
Jarad

8

Ne yazık ki karmaşık bir diziniz olduğunda, yalnızca np.sort(temp)[::-1]düzgün çalışır. Burada bahsedilen diğer iki yöntem etkili değildir.


@ anishtain4: "Karmaşık dizi" derken, karmaşık sayılar dizisini mi kastettiniz? Ya da başka bir tür karmaşıklığa sahip bir diziyi mi kastettiniz (öyleyse lütfen ne tür bir karmaşıklık olduğunu belirtin). Her iki durumda da, diğer yöntemlerin nasıl başarısız olabileceğine girerek cevabınız üzerinde biraz daha detaylandırabileceğinizi düşünüyorum. Teşekkürler.
Fountainhead

@fountainhead Karmaşık sayılar dizisini kastediyorum. Eski bir soru olduğu için, o zamandan beri daha fazla detaylandırmak için test durumumu hatırlamıyorum.
anishtain4

8

Boyutlara dikkat edin.

İzin Vermek

x  # initial numpy array
I = np.argsort(x) or I = x.argsort() 
y = np.sort(x)    or y = x.sort()
z  # reverse sorted array

Tam Ters

z = x[-I]
z = -np.sort(-x)
z = np.flip(y)
  • flipdeğişti 1.15, önceki sürümler gerekli . Çözüm: .1.14 axispip install --upgrade numpy

İlk Boyut Tersine Çevirildi

z = y[::-1]
z = np.flipud(y)
z = np.flip(y, axis=0)

İkinci Boyut Tersine Döndürüldü

z = y[::-1, :]
z = np.fliplr(y)
z = np.flip(y, axis=1)

Test yapmak

100 × 10 × 10 dizisinde 1000 kez test ediliyor.

Method       | Time (ms)
-------------+----------
y[::-1]      | 0.126659  # only in first dimension
-np.sort(-x) | 0.133152
np.flip(y)   | 0.121711
x[-I]        | 4.611778

x.sort()     | 0.024961
x.argsort()  | 0.041830
np.flip(x)   | 0.002026

Bu, esas olarak yeniden dizin oluşturmadan kaynaklanmaktadır argsort.

# Timing code
import time
import numpy as np


def timeit(fun, xs):
    t = time.time()
    for i in range(len(xs)):  # inline and map gave much worse results for x[-I], 5*t
        fun(xs[i])
    t = time.time() - t
    print(np.round(t,6))

I, N = 1000, (100, 10, 10)
xs = np.random.rand(I,*N)
timeit(lambda x: np.sort(x)[::-1], xs)
timeit(lambda x: -np.sort(-x), xs)
timeit(lambda x: np.flip(x.sort()), xs)
timeit(lambda x: x[-x.argsort()], xs)
timeit(lambda x: x.sort(), xs)
timeit(lambda x: x.argsort(), xs)
timeit(lambda x: np.flip(x), xs)

np.flip () - super
Darius

6

Merhaba, iki boyutlu bir uyuşuk diziyi tersine çevirmek için bir çözüm arıyordum ve işe yarayan hiçbir şey bulamadım, ancak sanırım birisinin aynı teknede olması durumunda yüklediğim bir çözüme rastladım.

x=np.sort(array)
y=np.fliplr(x)

np.sort, sizin istediğiniz gibi olmayan artan şekilde sıralar, ancak fliplr komutu satırları soldan sağa çevirir! Çalışıyor gibi görünüyor!

Umarım size yardımcı olur!

Sanırım yukarıdaki -np.sort (-a) ile ilgili öneriye benziyor, ancak her zaman işe yaramayacağı yorumuyla bunun için gitmekten vazgeçtim. Belki de benim çözümüm her zaman işe yaramayacak, ancak birkaç diziyle test ettim ve iyi görünüyor.


1

Önce diziyi sıralayabilir (varsayılan olarak artan) ve sonra np.flip () uygulayabilirsiniz ( https://docs.scipy.org/doc/numpy/reference/generated/numpy.flip.html )

Bilginize, datetime nesneleriyle de çalışır.

Misal:

    x = np.array([2,3,1,0]) 
    x_sort_asc=np.sort(x) 
    print(x_sort_asc)

    >>> array([0, 1, 2, 3])

    x_sort_desc=np.flip(x_sort_asc) 
    print(x_sort_desc)

    >>> array([3,2,1,0])

Dizilerinde NaN bulunanlar için dikkatli olun, önerilen çeşitli yöntemler farklı sonuçlar verir. Örneğin x = np.array([2,3,np.nan,1,0]) , np.flip(np.sort(x))yaklaşım [nan 3. 2. 1. 0.] verirken, -np.sort(-x)yaklaşım [3. 2. 1. 0. nan] verir.
Uwe Mayer

1

İşte hızlı bir numara

In[3]: import numpy as np
In[4]: temp = np.random.randint(1,10, 10)
In[5]: temp
Out[5]: array([5, 4, 2, 9, 2, 3, 4, 7, 5, 8])

In[6]: sorted = np.sort(temp)
In[7]: rsorted = list(reversed(sorted))
In[8]: sorted
Out[8]: array([2, 2, 3, 4, 4, 5, 5, 7, 8, 9])

In[9]: rsorted
Out[9]: [9, 8, 7, 5, 5, 4, 4, 3, 2, 2]

-3

bunu kullanmanızı öneririm ...

np.arange(start_index, end_index, intervals)[::-1]

Örneğin:

np.arange(10, 20, 0.5)
np.arange(10, 20, 0.5)[::-1]

Sonra yeniden canlandırmanız:

[ 19.5,  19. ,  18.5,  18. ,  17.5,  17. ,  16.5,  16. ,  15.5,
    15. ,  14.5,  14. ,  13.5,  13. ,  12.5,  12. ,  11.5,  11. ,
    10.5,  10. ]

1
Bu sorunu nasıl çözer? Bu arada - - Sadece tamamen alakasız, yeni (azalan) dizi oluştururken daha etkin bir şekilde yapılabilir: np.arange(20-0.5, 10-0.5, -0.5). Ancak bu farklı bir hikaye ve okunabilirliğin daha kötü olması nedeniyle tartışılabilir olabilir. Bir giriş dizisi hiç sıralanmamış
Daniel
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.