Как сделать эту операцию в numPy? - PullRequest
3 голосов
/ 14 марта 2012

У меня есть массив X трехмерных координат из N точек (N * 3), и я хочу вычислить расстояние по Евклиду между каждой парой точек.

Я могу сделать это, перебирая X и сравнивая их с порогом.

coords = array([v.xyz for v in vertices])
for vertice in vertices:
    tests = np.sum(array(coords - vertice.xyz) ** 2, 1) < threshold
    closest = [v for v, t in zip(vertices, tests) if t]

Возможно ли это сделать за одну операцию? Я вспоминаю линейную алгебру 10 лет назад и не могу найти способ сделать это.

Вероятно, это должен быть трехмерный массив (точка a, точка b, ось), а затем суммироваться по axis измерению.

edit: сам нашел решение, но оно не работает с большими наборами данных.

    coords = array([v.xyz for v in vertices])
    big = np.repeat(array([coords]), len(coords), 0)
    big_same = np.swapaxes(big, 0, 1)
    tests = np.sum((big - big_same) ** 2, 0) < thr_square

    for v, test_vector in zip(vertices, tests):
        v.closest = self.filter(vertices, test_vector)

Ответы [ 3 ]

2 голосов
/ 14 марта 2012

Использование scipy.spatial.distance. Если X представляет собой массив точек n × 3, вы можете получить матрицу расстояний n × n из

from scipy.spatial import distance
D = distance.squareform(distance.pdist(X))

Тогда ближайшей к точке i является точка с индексом

np.argsort(D[i])[1]

([1] пропускает значение по диагонали, которое будет возвращено первым.)

0 голосов
/ 14 марта 2012

Если xyz - это массив с вашими координатами, то следующий код вычислит матрицу расстояний (работает быстро до того момента, когда у вас будет достаточно памяти для хранения N ^ 2 расстояний):

xyz = np.random.uniform(size=(1000,3))
distances = (sum([(xyzs[:,i][:,None]-xyzs[:,i][None,:])**2 for i in range(3)]))**.5
0 голосов
/ 14 марта 2012

Я не совсем уверен, что вы спрашиваете здесь. Если вы вычисляете евклидово расстояние между каждой парой точек в N-точечном пространстве, для меня будет иметь смысл представить результаты в виде матрицы поиска. Таким образом, для N точек вы получите симметричную матрицу NxN. Элемент (3, 5) будет представлять расстояние между точками 3 и 5, тогда как элемент (2, 2) будет расстоянием между точкой 2 и самой собой (ноль). Вот как я бы сделал это для случайных точек:

import numpy as np

N = 5 

coords = np.array([np.random.rand(3) for _ in range(N)])
dist = np.zeros((N, N)) 

for i in range(N):
    for j in range(i, N): 
        dist[i, j] = np.linalg.norm(coords[i] - coords[j])
        dist[j, i] = dist[i, j]

print dist
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...