2010-04-24 9 views
23

나는 N 포인트 (x 및 y 좌표)를 유지하는 모양이 2 차원 인 (N, 2) 배열을 가지고 있습니다. 예를 들어 :여러 축으로 2D numpy 배열 정렬

array([[3, 2], 
     [6, 2], 
     [3, 6], 
     [3, 4], 
     [5, 3]]) 

내 포인트에 의해 정렬이되도록 정렬하고자하는 X 같은 좌표의 경우 Y로 다음 X 좌표합니다. 위의 배열은 다음과 같이한다 그래서이 정상적인 파이썬리스트 인 경우

array([[3, 2], 
     [3, 4], 
     [3, 6], 
     [5, 3], 
     [6, 2]]) 

, 난 그저 내가하고 싶은 일을하는 비교기를 정의하는 것이지만, 지금까지 내가 말할 수있는, NumPy와의 정렬 기능하지 않습니다 사용자 정의 비교기를 수락하십시오. 어떤 아이디어?


편집 : 아이디어를 제공해 주셔서 감사합니다! 1000000 개의 무작위 정수 포인트를 가진 빠른 테스트 케이스를 설정하고 실행할 수있는 벤치 마크를했습니다 (미안하지만, 지금은 numpy를 업그레이드 할 수 없습니다).

Mine: 4.078 secs 
mtrw: 7.046 secs 
unutbu: 0.453 secs 

답변

39

: aC_CONTIGUOUS 경우

import numpy as np  
a = np.array([(3, 2), (6, 2), (3, 6), (3, 4), (5, 3)]) 

ind = np.lexsort((a[:,1],a[:,0]))  

a[ind] 
# array([[3, 2], 
#  [3, 4], 
#  [3, 6], 
#  [5, 3], 
#  [6, 2]]) 

a.ravel()보기를 반환합니다. b 이후

a = np.array([(3, 2), (6, 2), (3, 6), (3, 4), (5, 3)]) 
dt = [('col1', a.dtype),('col2', a.dtype)] 
assert a.flags['C_CONTIGUOUS'] 
b = a.ravel().view(dt) 
b.sort(order=['col1','col2']) 

b 종류 a으로 정렬, a의보기입니다 : 그 @ars's method을, 사실이라면, 약간 ravel 대신 flatten을 사용하여 변형 한, 현재 위치에서a를 정렬하는 좋은 방법을 산출 잘 :

print(a) 
# [[3 2] 
# [3 4] 
# [3 6] 
# [5 3] 
# [6 2]] 
+0

아, 나는 문서에서 lexsort를 보았지만이 문제에 어떻게 적용되는지 알 수 없었습니다. 감사! – perimosocordiae

+3

예, 종종 문서를 이해하는 데 어려움이 있습니다. 예는 훨씬 더 밝아지는 경향이 있습니다. 문제는 예를 가지고 놀고 나면 문서를 다시 읽고 문서가 완벽하게 명확하다는 것을 알 수 있습니다. :-) – unutbu

+0

이것은 배열의 복사본을 만들고 있습니까? – g33kz0r

2

EDIT : 제거 된 대답이 잘못되었습니다.

from numpy import array 

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

b = a.flatten() 
b.dtype = [('x', '<i4'), ('y', '<i4')] 
b.sort() 
b.dtype = '<i4' 
b.shape = a.shape 

print b 

원하는 출력을 제공합니다 :

여기에 중간 구조화 된 배열을 사용하여 작업을 수행하는 한 가지 방법이다이 비록 그것에 대해 이동하는 아주 좋은 방법 인 경우

[[3 2] 
[3 4] 
[3 6] 
[5 3] 
[6 2]] 

확실하지 않음 .

+0

내 포인트에 대한 x와 y 사이의 연관을 상실하기 때문에, 잘 작동을하지 않습니다. – perimosocordiae

+0

오, 네 말이 맞아. 죄송합니다. 내 대답이 업데이트되었습니다. – ars

+0

흠. 이를 실행할 때'b.shape = a.shape' 줄에 오류가 발생합니다 : "ValueError : 새 배열의 전체 크기는 변경되지 않아야합니다". 나는 numpy 1.2.1과 함께 파이썬 2.6.2를 돌리고있다. – perimosocordiae

1

나는 그 방법을 발견

from numpy import array 
a = array([(3,2),(6,2),(3,6),(3,4),(5,3)]) 
array(sorted(sorted(a,key=lambda e:e[1]),key=lambda e:e[0])) 

그것은 두 번 분류 (대신 빠른 NumPy와 종류의 일반 파이썬 sorted 기능을 사용) 할 필요가 꽤 끔찍하지만 하나에 잘 맞지 않습니다 선. lexsort를 사용

3

np.complex_sort을 사용할 수 있습니다. 이것은 부동 소수점 데이터를 변경하는 부작용이, 그게 문제가되지 않습니다 희망 : 나는 똑같은 고민 그냥 도움을 얻고 문제를 해결했다

>>> a = np.array([[3, 2], [6, 2], [3, 6], [3, 4], [5, 3]]) 
>>> atmp = np.sort_complex(a[:,0] + a[:,1]*1j) 
>>> b = np.array([[np.real(x), np.imag(x)] for x in atmp]) 
>>> b 
array([[ 3., 2.], 
     [ 3., 4.], 
     [ 3., 6.], 
     [ 5., 3.], 
     [ 6., 2.]]) 
+1

나는 당신이 영리함 상을 획득했다고 생각합니다; 나는 y- 좌표를 가상으로 만드는 것을 생각하지 않았을 것입니다! – perimosocordiae

+0

하지만 개가 천천히! 죄송합니다. 게시했을 때 실적을 고려하지 않았습니다. – mtrw

3

.배열은 열 이름 (구조적 배열)가있는 경우이 원활하게 작동하고 나는이가하는 엑셀 같은 논리를 사용하여 정렬하는 아주 간단한 방법이라고 생각 :

array_name[array_name[['colname1','colname2']].argsort()] 

참고 정렬 기준을 둘러싸는 이중 브라켓. 물론, 정렬 기준으로 2 개 이상의 열을 사용할 수 있습니다.

13

제목은 "2 차원 배열 정렬"이라고 말합니다. 질문자는 (N,2) 모양의 배열을 사용하지만, 사람들이 실제로 찾고있을 수도있는대로 (N,M) 배열로 작동하도록 unutbu의 솔루션을 일반화하는 것이 가능합니다.

한 반대 순서로 lexsort에 모든 열을 전달하는 부정적인 step와 배열 사용 슬라이스 표기법을 transpose 수 :

>>> import numpy as np 
>>> a = np.random.randint(1, 6, (10, 3)) 
>>> a 
array([[4, 2, 3], 
     [4, 2, 5], 
     [3, 5, 5], 
     [1, 5, 5], 
     [3, 2, 1], 
     [5, 2, 2], 
     [3, 2, 3], 
     [4, 3, 4], 
     [3, 4, 1], 
     [5, 3, 4]]) 

>>> a[np.lexsort(np.transpose(a)[::-1])] 
array([[1, 5, 5], 
     [3, 2, 1], 
     [3, 2, 3], 
     [3, 4, 1], 
     [3, 5, 5], 
     [4, 2, 3], 
     [4, 2, 5], 
     [4, 3, 4], 
     [5, 2, 2], 
     [5, 3, 4]]) 
3

numpy_indexed 패키지 (면책 조항 : 나는 그것의 저자) 해결하는 데 사용할 수 있습니다 효율적인 완전히 벡터화 방식으로 처리-에-ND 배열 문제 이런 종류 :

import numpy_indexed as npi 
npi.sort(a) # by default along axis=0, but configurable