Как рассчитать евклидово расстояние между парой строк массива numpy

У меня есть массив numpy, например:

import numpy as np
a = np.array([[1,0,1,0],
             [1,1,0,0],
             [1,0,1,0],
             [0,0,1,1]])

Я хотел бы рассчитать euclidian distance между каждой парой строк.

from scipy.spatial import distance
for i in range(0,a.shape[0]):
    d = [np.sqrt(np.sum((a[i]-a[j])**2)) for j in range(i+1,a.shape[0])]
    print(d)

[1.4142135623730951, 0.0, 1.4142135623730951]

[1.4142135623730951, 2.0]

[1.4142135623730951]

[]

Есть ли лучший питонический способ сделать это, так как мне нужно запустить этот код на огромном массиве numpy?


person Rashmi Singh    schedule 12.04.2017    source источник
comment
Точки имеют произвольные размеры или всегда 4d?   -  person Willem Van Onsem    schedule 12.04.2017
comment
Вы смотрели на : distance.pdist? Это должно решить это с помощью: distance.pdist(a). Каким должен быть конечный результат?   -  person Divakar    schedule 12.04.2017
comment
@Divakar среди евклидовых расстояний между всеми парами векторов-строк Мне нужны k самых дальних векторов.   -  person Rashmi Singh    schedule 12.04.2017
comment
@divakar Сэр, это сработало   -  person Rashmi Singh    schedule 12.04.2017
comment
Также взгляните на KDTree — docs.scipy.org/doc/scipy-0.14.0/reference/generated/   -  person Divakar    schedule 12.04.2017


Ответы (3)


И для полноты, einsum часто используется для расчета расстояний.

a = np.array([[1,0,1,0],
         [1,1,0,0],
         [1,0,1,0],
         [0,0,1,1]])

b = a.reshape(a.shape[0], 1, a.shape[1])

np.sqrt(np.einsum('ijk, ijk->ij', a-b, a-b))

array([[ 0.        ,  1.41421356,  0.        ,  1.41421356],
       [ 1.41421356,  0.        ,  1.41421356,  2.        ],
       [ 0.        ,  1.41421356,  0.        ,  1.41421356],
       [ 1.41421356,  2.        ,  1.41421356,  0.        ]])
person NaN    schedule 12.04.2017

С точки зрения чего-то более «элегантного», вы всегда можете использовать попарное евклидово расстояние scikitlearn:

from sklearn.metrics.pairwise import euclidean_distances
euclidean_distances(a,a)

с тем же выходом, что и один массив.

array([[ 0.        ,  1.41421356,  0.        ,  1.41421356],
       [ 1.41421356,  0.        ,  1.41421356,  2.        ],
       [ 0.        ,  1.41421356,  0.        ,  1.41421356],
       [ 1.41421356,  2.        ,  1.41421356,  0.        ]])
person comendeiro    schedule 12.04.2017
comment
Я думаю, что это дает мне евклидово расстояние между каждой парой точек, но я хочу его между каждой парой строк. Предположим, что одна строка представляет один вектор 1d. - person Rashmi Singh; 12.04.2017
comment
Извините, я забыл упомянуть в своем вопросе, что одна строка - это один вектор 1d. - person Rashmi Singh; 12.04.2017
comment
Это сработало. Спасибо. Я неправильно понял. Каждая запись представляет собой расстояние между i-й и j-й строками массива mXn, где i‹ j‹m. - person Rashmi Singh; 12.04.2017

Я использовал itertools.combinations вместе с np.linalg.norm разностного вектора (это евклидово расстояние):

import numpy as np
import itertools
a = np.array([[1,0,1,0],
              [1,1,0,0],
              [1,0,1,0],
              [0,0,1,1]])

print([np.linalg.norm(x[0]-x[1]) for x in itertools.combinations(a, 2)])

Для понимания взгляните на этот пример из документов:
combinations('ABCD', 2) дает AB AC AD BC BD CD. В вашем случае A, B, C и D являются строками вашей матрицы a, поэтому термин x[0]-x[1], появляющийся в приведенном выше коде, представляет собой разностный вектор векторов в строках a.

person Michael H.    schedule 12.04.2017