NumPy에서 배열을 열로 정렬


336

NumPy에서 n 번째 열을 기준으로 배열을 정렬하려면 어떻게합니까?

예를 들어

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

두 번째 열을 기준으로 행을 정렬하고 싶습니다.

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

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

29
데이비드, 당신은 질문의 요점을 얻지 못합니다. 그는 각 행의 순서를 동일하게 유지하려고합니다.
marcorossi

@marcorossi 요점을 얻었지만 예를 들어 여러 가지 가능한 답변이 있었기 때문에 예제가 매우 잘못 작성되었습니다 (그러나 OP의 요청을 충족시키지 못했을 것입니다). 내 의견을 기반으로 한 이후의 편집은 실제로 승인되었습니다 (그러나 광산은 거부되었습니다.). 이제 모든 것이 정상입니다.
데이비드

답변:


141

@ 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 's는 내가 아는 한 실제로 그것을하는 가장 우아한 방법입니다 ...

이 방법의 유일한 장점은 "order"인수가 검색을 정렬 할 필드 목록이라는 것입니다. 예를 들어 order = [ 'f1', 'f2', 'f0']을 제공하여 두 번째 열, 세 번째 열, 첫 번째 열을 기준으로 정렬 할 수 있습니다.


3
내 numpy 1.6.1rc1에서 증가합니다ValueError: new type not compatible with array.
Clippit

9
"올바른"방법이 덜 추악하다는 기능 요청을 제출하는 것이 합리적입니까?
endolith

4
배열의 값이 무엇입니까 float? 무엇을 바꿔야합니까?
Marco

1
그리고 a = np.array([['a',1,2,3],['b',4,5,6],['c',0,0,1]])어떤 접근법을 따라야합니까?
ePascoal

10
Steve보다이 방법의 주요 장점 중 하나는 매우 큰 배열을 정렬 할 수 있다는 것입니다. 충분히 큰 배열의 경우 반환 된 인덱스 np.argsort는 많은 메모리를 차지할 수 있으며 그 위에 배열을 사용하여 인덱싱하면 정렬중인 배열의 복사본도 생성됩니다.
ali_m

737

나는 이것이 효과가 있다고 생각한다. a[a[:,1].argsort()]

이것은 두 번째 열을 나타내며 a그에 따라 정렬합니다.


2
이것은 명확하지 않습니다 1. 여기에 무엇이 있습니까? 정렬 할 인덱스?
orezvani

29
[:,1]의 두 번째 열을 나타냅니다 a.
Steve Tjoa

60
역 정렬을 원한다면 이것을 수정하십시오a[a[:,1].argsort()[::-1]]
Steven C. Howell

1
단순 해 보이고 작동합니다! 빠르 np.sort거나 빠르지 않습니까?
Václav Pavlík

14
나는 이것을 읽기가 더 쉽다는 것을 발견했다 :ind = np.argsort( a[:,1] ); a = a[ind]
poppie

32

Steve Tjoa의 방법에 따라 mergesort와 같은 안정적인 정렬을 사용하고 인덱스를 가장 중요하지 않은 열에서 가장 중요한 열로 정렬하여 여러 열을 정렬 할 수 있습니다.

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로 정렬됩니다.


4
First Sort가 안정적 일 필요가없는 이유는 무엇입니까?
Little Bobby Tables

10
좋은 질문-안정은 넥타이가있을 때 원래 순서를 유지하고 정렬되지 않은 파일의 원래 순서는 관련이 없다는 것을 의미합니다.
JJ

이것은 정말로 중요한 중요한 것 같습니다. 조용히 정렬되지 않은 목록을 갖는 것은 좋지 않습니다.
서투른 고양이

19

누군가 프로그램의 중요한 부분에서 정렬을 사용하려는 경우 다른 제안에 대한 성능 비교가 있습니다.

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사용한 색인 생성입니다 ...


19

에서 파이썬 문서 위키 , 나는 당신이 할 수 있다고 생각 :

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

21
이 솔루션을 사용하면 NumPy 배열 대신 목록을 얻으므로 항상 편리하지는 않을 수 있습니다 (메모리를 많이 차지하거나 속도가 느릴 수 있음).
Eric O Lebigot

이 "솔루션"은 실제로 거의 무한대에 가깝습니다
Jivan

16

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

3
올바른 일반화는 a[np.lexsort(a.T[cols])]입니다. cols=[1]원래 질문의 어디에 .
라디오 제어

5

나는 비슷한 문제가 있었다.

내 문제:

SVD를 계산하고 고유 값 을 정렬해야합니다. 을 내림차순 . 그러나 고유 값과 고유 벡터 간의 매핑을 유지하고 싶습니다. 내 고유 값은 첫 번째 행에 있었고 해당 고유 벡터는 같은 열에있었습니다.

그래서 첫 번째 행을 기준으로 2 차원 배열을 내림차순으로 정렬합니다.

내 솔루션

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

어떻게 작동합니까?

a[0,] 정렬하려는 첫 번째 행입니다.

이제 argsort를 사용하여 인덱스 순서를 가져옵니다.

[::-1]내림차순이 필요 하기 때문에 사용 합니다.

마지막으로 a[::, ...]올바른 순서로 열이있는보기를 얻는 데 사용 합니다.


1

좀 더 복잡한 lexsort예-첫 번째 열에서 내림차순으로 두 번째에서 두 번째로 오름차순. 트릭 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]])

0

다음은 모든 열을 고려한 또 다른 솔루션 입니다 ( 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]])

0

간단히 sort를 사용하여 정렬하려는 열수를 사용하십시오.

a = np.array([1,1], [1,-1], [-1,1], [-1,-1]])
print (a)
a=a.tolist() 
a = np.array(sorted(a, key=lambda a_entry: a_entry[0]))
print (a)

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]]
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.