web-dev-qa-db-ja.com

NumPyの配列を列でソートする

NumPyの配列をn列目でソートするにはどうすればよいですか?

例えば、

a = array([[9, 2, 3],
           [4, 5, 6],
           [7, 0, 5]])

戻ってくるように、2列目で行を並べ替えたいのですが。

array([[7, 0, 5],
       [9, 2, 3],
       [4, 5, 6]])
267
user248237

@ steve が実際に最もエレガントな方法です。

「正しい」方法については、 numpy.ndarray.sort のorderキーワード引数を参照してください。

ただし、配列はフィールドを持つ配列(構造化配列)として表示する必要があります。

あなたが最初にフィールドであなたの配列を定義しなかったならば、「正しい」方法はかなり醜いです...

簡単な例として、並べ替えてコピーを返すには、次のようにします。

In [1]: import numpy as np

In [2]: a = np.array([[1,2,3],[4,5,6],[0,0,1]])

In [3]: np.sort(a.view('i8,i8,i8'), order=['f1'], axis=0).view(np.int)
Out[3]: 
array([[0, 0, 1],
       [1, 2, 3],
       [4, 5, 6]])

その場でソートするには:

In [6]: a.view('i8,i8,i8').sort(order=['f1'], axis=0) #<-- returns None

In [7]: a
Out[7]: 
array([[0, 0, 1],
       [1, 2, 3],
       [4, 5, 6]])

私が知っている限りでは、@ Steveは本当にそれを行うための最もエレガントな方法です...

このメソッドの唯一の利点は、 "order"引数が検索を順序付けるためのフィールドのリストであるということです。たとえば、order = ['f1'、 'f2'、 'f0']を指定すると、2列目、3列目、1列目の順に並べ替えることができます。

115
Joe Kington

私はこれがうまくいくと思います:a[a[:,1].argsort()]

これはaの2列目を示し、それに基づいてソートします。

592
Steve Tjoa

Steve Tjoaの方法に従って、マージソートのような安定したソートを使用し、インデックスを最下位から最上位の列にソートすることで、複数の列をソートできます。

a = a[a[:,2].argsort()] # First sort doesn't need to be stable.
a = a[a[:,1].argsort(kind='mergesort')]
a = a[a[:,0].argsort(kind='mergesort')]

これは、列0、次に1、次に2の順にソートされます。

23
J.J

Python documentation wiki から、私はあなたができると思います:

a = ([[1, 2, 3], [4, 5, 6], [0, 0, 1]]); 
a = sorted(a, key=lambda a_entry: a_entry[1]) 
print a

出力は以下のとおりです。

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

誰かが自分のプログラムの重要な部分でソートを利用したい場合は、さまざまな提案に対するパフォーマンスの比較を次に示します。

import numpy as np
table = np.random.Rand(5000, 10)

%timeit table.view('f8,f8,f8,f8,f8,f8,f8,f8,f8,f8').sort(order=['f9'], axis=0)
1000 loops, best of 3: 1.88 ms per loop

%timeit table[table[:,9].argsort()]
10000 loops, best of 3: 180 µs per loop

import pandas as pd
df = pd.DataFrame(table)
%timeit df.sort_values(9, ascending=True)
1000 loops, best of 3: 400 µs per loop

ですから、 argsort でインデックスを付けるのが一番早い方法です...

16
prl900

NumPyメーリングリスト から、もう一つの解決策があります:

>>> a
array([[1, 2],
       [0, 0],
       [1, 0],
       [0, 2],
       [2, 1],
       [1, 0],
       [1, 0],
       [0, 0],
       [1, 0],
      [2, 2]])
>>> a[np.lexsort(np.fliplr(a).T)]
array([[0, 0],
       [0, 0],
       [0, 2],
       [1, 0],
       [1, 0],
       [1, 0],
       [1, 0],
       [1, 2],
       [2, 1],
       [2, 2]])
14
fgregg

私は同様の問題を抱えていました。

私の問題:

SVDを計算したいので、 固有値 を降順に並べ替える必要があります。しかし、私は固有値と固有ベクトルの間の写像を保ちたいのです。私の固有値は最初の行にあり、その下の対応する固有ベクトルは同じ列にあります。

そのため、2次元配列を最初の行で降順に列方向にソートしたいと思います。

私の解決策

a = a[::, a[0,].argsort()[::-1]]

それで、これはどのように機能しますか?

a[0,]は、並べ替えたい最初の行です。

今度はargsortを使ってインデックスの順序を取得します。

降順が必要なので[::-1]を使用します。

最後にa[::, ...]を使用して、正しい順序で列を含むビューを取得します。

3
xuma202

もう少し複雑なlexsortの例 - 1列目で降順、2番目で昇順。 lexsortのコツは、行順(つまり.T)でソートし、最後に優先することです。

In [120]: b=np.array([[1,2,1],[3,1,2],[1,1,3],[2,3,4],[3,2,5],[2,1,6]])
In [121]: b
Out[121]: 
array([[1, 2, 1],
       [3, 1, 2],
       [1, 1, 3],
       [2, 3, 4],
       [3, 2, 5],
       [2, 1, 6]])
In [122]: b[np.lexsort(([1,-1]*b[:,[1,0]]).T)]
Out[122]: 
array([[3, 1, 2],
       [3, 2, 5],
       [2, 1, 6],
       [2, 3, 4],
       [1, 1, 3],
       [1, 2, 1]])
1
hpaulj

これは、すべての列を考慮した別の解決策です( J.J の答えのより簡潔な方法)。

ar=np.array([[0, 0, 0, 1],
             [1, 0, 1, 0],
             [0, 1, 0, 0],
             [1, 0, 0, 1],
             [0, 0, 1, 0],
             [1, 1, 0, 0]])

Lexsortで並べ替え

ar[np.lexsort(([ar[:, i] for i in range(ar.shape[1]-1, -1, -1)]))]

出力:

array([[0, 0, 0, 1],
       [0, 0, 1, 0],
       [0, 1, 0, 0],
       [1, 0, 0, 1],
       [1, 0, 1, 0],
       [1, 1, 0, 0]])
0
Sefa