web-dev-qa-db-ja.com

numpy配列を降順で効率的にソートしますか?

この特定の質問がこれまでに聞かれたことがないことに驚いていますが、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は、並べ替え操作で比較の符号を変更するパラメータを受け入れて、物事を逆順で取得するようには見えません。

78

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
101
>>> 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])
55
Mike O'Connor

短い配列の場合は、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
12
Kasrâmvd

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

6
anishtain4

こんにちは、2次元のnumpy配列を逆に並べ替える解決策を探していましたが、機能するものは見つかりませんでしたが、同じボートにいる人のためにアップロードしている解決策につまずいたと思います。

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

np.sortは昇順でソートしますが、これは必要なものではありませんが、コマンドfliplrは行を左から右に反転します!動作しているようです!

それがあなたを助けることを願っています!

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

2
Naz

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

させて

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)
  • 1.15 で変更されたflip、以前のバージョン 1.14requiredaxis。解決策:pip install --upgrade numpy

逆転した最初の次元

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

二次元目反転

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)
0
A. West

私はこれを使用することをお勧めします...

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. ]
0