numpy配列を効率的に降順に並べ替えますか?


121

この特定の質問が以前に尋ねられたことがないことに驚いていますが、SOやのドキュメントでは実際には見つかりませんでしたnp.sort

たとえば、整数を保持するランダムなnumpy配列があるとします。例:

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

並べ替えると、デフォルトで昇順になります。

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

しかし、私はソリューションを降順に並べ替えたいです。

今、私はいつでもできることを知っています:

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

しかし、この最後のステートメントは効率的ですか?昇順でコピーを作成し、このコピーを逆にして結果を逆順で取得しませんか?これが事実である場合、効率的な代替手段はありますか?np.sort逆の順序で物事を取得するために、並べ替え操作で比較の符号を変更するパラメーターを受け入れるようには見えません。

回答:


139

temp[::-1].sort()配列を所定の位置にソートしnp.sort(temp)[::-1]、新しい配列を作成します。

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
ありがとう、しかしtemp[::-1].sort()それが逆の順序でソートする必要があることをどうやって知っていますか?私がそれを読む方法は、元の配列を逆にし、次にそれを(昇順で)ソートします。元の配列を逆にして(ランダムな順序で)、昇順で並べ替えると、配列が逆の順序で返されるのはなぜですか?
Amelio Vazquez-Reina

14
これはかなり直感的ではないので、文書化されていますか?
ebarr 2014年

18
これ[::-1]は、実際に配列を並べ替えるのではなく、numpyに配列を逆方向に反復するように指示するだけなので、機能するように見えます。そのため、インプレースソートが発生すると、実際には昇順でソートされ、ビットが移動しますが、後方反復の部分は変更されません。
perimosocordiae 14年

45
このa=np.array((...))イディオムa[::-1]は何も反転させず、同じデータの新しいビューであり、具体的にはミラービューです。このメソッドa[::-1].sort() は、ミラーリングされたイメージ動作します。つまり、ミラーリングされたイメージ内の小さいアイテムをsort移動すると、実際には配列の実メモリブロック内でに移動されます。ミラーリングされたビューは昇順でソートされ、実際のデータは降順でソートされます。いくつかの異なるコインと鏡を使って、ご自分でご自宅でお試しください!a
gboffi 2014年

30
これは、np.sort(temp,order='descending')この種のハックを要求するのではなく、読み取り可能なパラメータとして追加する必要があります
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
ベストの答え-短いと甘い、との知識がないaxisこれにnp.sort適用されたが必要です。
ルークデイビス

2
これは、アレイの前面ではなく背面にsをnp.sort(temp)[::-1]配置することとは異なりnanます。良いか悪いのかどうかは議論のためにアップしている...
ベン

15

短い配列の場合np.argsort()、ソートされたネガティブ配列のインデックスを検索して使用することをお勧めします。これは、ソートされた配列を逆にするよりもわずかに高速です。

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)]おそらくこのページの他の人への最善のアプローチです。-1ステップの反転はなく、マイナス記号を1つ減らす必要があります。
Jarad

8

複雑な配列がある場合は残念ながら、np.sort(temp)[::-1]正しく動作します。ここで説明した他の2つの方法は効果的ではありません。


@ anishtain4:「複素数配列」とは、複素数の配列を意味するのですか?それとも、他の種類の複雑さを持つ配列を意味しましたか(そうであれば、plsはどのような複雑さを指定するか)。どちらの場合でも、他の方法が失敗する可能性がある方法を理解することで、回答をさらに詳しく説明できると思います。ありがとう。
噴水

@fountainhead私は複素数の配列を意味します。それは古い質問なので、それ以上詳しく説明するためのテストケースを覚えていません。
anishtain4

7

寸法に注意してください。

しましょう

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

完全リバース

z = x[-I]
z = -np.sort(-x)
z = np.flip(y)
  • flipで変更され1.15、以前のバージョンが必要でした。ソリューション:。1.14 axispip install --upgrade numpy

最初の次元を反転

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

2番目の次元を反転

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

テスト中

100×10×10アレイで1000回テスト。

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

これは主にでなく、インデックスの再作成によるもの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)

6

こんにちは私は2次元のnumpy配列を逆ソートするための解決策を探していましたが、何も機能しませんでしたが、誰かが同じボートにいる場合に備えて、アップロードしている解決策に出くわしました。

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

np.sortは昇順でソートしますが、これは希望どおりではありませんが、fliplrコマンドは行を左から右に反転します!動作するようです!

お役に立てば幸いです。

これは上記の-np.sort(-a)に関する提案に似ていると思いますが、常に機能するとは限らないというコメントでそれを先延ばしにしました。おそらく私のソリューションは常に機能するとは限りませんが、いくつかのアレイでテストしたところ、問題はないようです。


1

最初に配列をソートし(デフォルトでは昇順)、次にnp.flip()を適用できます (https://docs.scipy.org/doc/numpy/reference/generated/numpy.flip.html

FYIこれは、datetimeオブジェクトでも機能します。

例:

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

配列にNaNがある場合は注意が必要です。提案されているさまざまな方法では、異なる結果が得られます。たとえばx = np.array([2,3,np.nan,1,0]) np.flip(np.sort(x))アプローチが[nan 3. 2. 1. 0.]を生成する場合、-np.sort(-x)アプローチは[3. 2. 1. 0. nan]を生成します。
Uwe Mayer

1

ここに簡単なトリックがあります

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

私はこれを使うことを勧めます...

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

例えば:

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

次に、あなたの再攻撃:

[ 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
これはどのように問題を解決しますか?途中で- -あなたは完全に、関係のない、新しい(降順)配列作成している、より効率的な方法で行うことができるが:np.arange(20-0.5, 10-0.5, -0.5)。しかし、それは別の話であり、読みやすさが悪いため、議論の余地があるかもしれません。入力配列はソートされていません
Daniel
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.