2016-10-14 3 views
1

좌표가 NumPy 배열입니다. 예를 들어, 이것을 사용합니다.NumPy 좌표 배열 사이의 삼각형 행렬을 계산하십시오.

In [1]: np.random.seed(123) 
In [2]: coor = np.random.randint(10, size=12).reshape(-1,3) 
In [3]: coor 
Out[3]: array([[2, 2, 6], 
       [1, 3, 9], 
       [6, 1, 0], 
       [1, 9, 0]]) 

모든 좌표 사이의 삼각 행렬을 원합니다. 간단한 방법은 I는

In [8]: dist = np.sqrt(((coor[:, None, :] - coor) ** 2).sum(-1)) 
를 사용하여 반복 피할 수있는, 모든 결과

In [7]: dist 
Out[7]: array([[ 0.  , 3.31662479, 7.28010989, 9.2736185 ], 
       [ 0.  , 0.  , 10.48808848, 10.81665383], 
       [ 0.  , 0.  , 0.  , 9.43398113], 
       [ 0.  , 0.  , 0.  , 0.  ]]) 

가 NumPy와 활용 거리의 상 삼각 행렬 인 상태

In [4]: n_coor = len(coor) 
In [5]: dist = np.zeros((n_coor, n_coor)) 
In [6]: for j in xrange(n_coor): 
      for k in xrange(j+1, n_coor): 
       dist[j, k] = np.sqrt(np.sum((coor[j] - coor[k]) ** 2)) 

좌표 위에 이중 루프를 코딩하는 것

하지만 결과는 전체 행렬

In [9]: dist 
Out[9]: array([[ 0.  , 3.31662479, 7.28010989, 9.2736185 ], 
       [ 3.31662479, 0.  , 10.48808848, 10.81665383], 
       [ 7.28010989, 10.48808848, 0.  , 9.43398113], 
       [ 9.2736185 , 10.81665383, 9.43398113, 0.  ]]) 

이 한 행 버전은 2048 좌표 (10 초 대신 4 초)를 사용하는 경우 대략 절반의 시간이 걸리지 만 대칭 행렬을 얻는 데 필요한 두 배의 계산을 수행합니다. 삼각형 행렬 만 얻을 수 있도록 한 줄 명령을 조정할 수있는 방법이 있습니까 (추가 2 배 속도 향상, 즉 2 초)?

+0

필요한 모든하지 매트릭스 거리, 경우 [SciPy의'pdist' (http://docs.scipy.org/doc/scipy/reference/ generated/scipy.spatial.distance.pdist.html)는 @Divaker에 의해 소개 된 것과 똑같이 반환합니다 ('trip_indices' 또는 boolean-indexing을 사용할 필요가 없습니다). –

답변

1

해당 거리를 얻으려면 SciPy's pdist method을 사용할 수 있습니다. 그래서, 우리가 출력 배열을 초기화 한 후

from scipy.spatial.distance import pdist 

n_coor = len(coor) 
dist = np.zeros((n_coor, n_coor)) 
row,col = np.triu_indices(n_coor,1) 
dist[row,col] = pdist(coor) 

또는 그 거리와 상위 삼각 값을 설정해야합니다, 우리는 마지막 두 줄

dist[np.arange(n_coor)[:,None] < np.arange(n_coor)] = pdist(coor) 
를 대체 값을 지정하는 부울 인덱싱을 사용할 수 있습니다

런타임 테스트

기능 :

,515,
def subscripted_indexing(coor): 
    n_coor = len(coor) 
    dist = np.zeros((n_coor, n_coor)) 
    row,col = np.triu_indices(n_coor,1) 
    dist[row,col] = pdist(coor) 
    return dist 

def boolean_indexing(coor): 
    n_coor = len(coor) 
    dist = np.zeros((n_coor, n_coor)) 
    r = np.arange(n_coor) 
    dist[r[:,None] < r] = pdist(coor) 
    return dist 

타이밍 :

In [110]: # Setup input array 
    ...: coor = np.random.randint(0,10, (2048,3)) 

In [111]: %timeit subscripted_indexing(coor) 
10 loops, best of 3: 91.4 ms per loop 

In [112]: %timeit boolean_indexing(coor) 
10 loops, best of 3: 47.8 ms per loop 
+0

니스! 'boolean-indexing '이없는 2048 좌표의 실행은 588ms 였고'boolean-indexing'은 135ms가 걸렸습니다. –

+0

@ stvn66 그래, 비슷한 결과가 여기에 있습니다! 게시물에 추가되었습니다. – Divakar

+0

몇 개의 좌표로 테스트합니까? 나는 단지 몇 가지 (예를 들어, 나의 예에서 4 개)를 사용하여 인위적인 차이를 만들어 냈습니다. –

관련 문제