NumPyの配列をn番目の列でソートするにはどうすればよいですか?
例えば、
a = array([[9, 2, 3],
[4, 5, 6],
[7, 0, 5]])
行を2番目の列で並べ替えて、次のようにしたいと思います。
array([[7, 0, 5],
[9, 2, 3],
[4, 5, 6]])
NumPyの配列をn番目の列でソートするにはどうすればよいですか?
例えば、
a = array([[9, 2, 3],
[4, 5, 6],
[7, 0, 5]])
行を2番目の列で並べ替えて、次のようにしたいと思います。
array([[7, 0, 5],
[9, 2, 3],
[4, 5, 6]])
回答:
「正しい」方法については、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番目の列の順に並べ替えることができます。
ValueError: new type not compatible with array.
float
か?何か変更すべきですか?
a = np.array([['a',1,2,3],['b',4,5,6],['c',0,0,1]])
どのようなアプローチに従う必要がありますか?
np.argsort
大量のメモリを占有する可能性があり、その上、配列を使用したインデックス付けによって、ソートされる配列のコピーも生成されます。
私はこれがうまくいくと思います: a[a[:,1].argsort()]
これは、2番目の列を示し、a
それに基づいてソートされます。
1
、ここには何がありますか?ソートするインデックス?
[:,1]
の2列目を示しますa
。
a[a[:,1].argsort()[::-1]]
np.sort
ですか?
ind = np.argsort( a[:,1] ); a = a[ind]
マージソートのような安定したソートを使用し、最下位のカラムから最上位のカラムへとインデックスをソートすることにより、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の順にソートされます。
Pythonドキュメントの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]]]
プログラムの重要な部分でソートを利用したい場合は、さまざまな提案のパフォーマンス比較を以下に示します。
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を使用したインデックス付けは、これまでで最も速い方法のようです...
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]])
a[np.lexsort(a.T[cols])]
です。cols=[1]
元の質問のどこに。
同様の問題がありました。
私の問題:
SVDを計算し、固有値を降順に並べ替える必要があります。しかし、固有値と固有ベクトルの間のマッピングを維持したいと思います。私の固有値は最初の行にあり、その下の対応する固有ベクトルは同じ列にありました。
したがって、2次元配列を最初の行で列ごとに降順に並べ替えたいと思います。
私の解決策
a = a[::, a[0,].argsort()[::-1]]
これはどのように機能するのでしょうか?
a[0,]
ソートしたい最初の行です。
次に、argsortを使用してインデックスの順序を取得します。
[::-1]
降順が必要なので使用します。
最後にa[::, ...]
、列を正しい順序で表示するために使用します。
もう少し複雑なlexsort
例-1番目の列で降順、2番目の列で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]])
これは、すべての列を考慮した別の解決策です(JJの回答のよりコンパクトな方法)。
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]])
それは古い質問ですが、これを2次元よりも高い配列に一般化する必要がある場合は、簡単に一般化できる解決策を次に示します。
np.einsum('ij->ij', a[a[:,1].argsort(),:])
これは2次元にとってはやり過ぎであり、a[a[:,1].argsort()]
@ steveの回答ごとに十分ですが、その回答をより高い次元に一般化することはできません。この質問で3D配列の例を見つけることができます。
出力:
[[7 0 5]
[9 2 3]
[4 5 6]]
np.sort(a, axis=0)
、与えられた行列に対して十分な解決策になるので、本当に悪い例です。より良い例を含む編集を提案しましたが、拒否されましたが、実際には質問の方がはるかに明確です。例はa = numpy.array([[1, 2, 3], [6, 5, 2], [3, 1, 1]])
、希望する出力のようなものである必要がありますarray([[3, 1, 1], [1, 2, 3], [6, 5, 2]])