简体   繁体   English

用numpy计算距离矩阵

[英]Compute distance matrix with numpy

I am trying to compute a "distance matrix" matrix to position using numpy. 我正在尝试使用numpy计算一个“距离矩阵”矩阵来定位。 To put it more clearly, I have a matrix representing positions in a 2-D grid: 更清楚地说,我有一个表示2D网格中位置的矩阵:

array([[[0, 0],
    [1, 0],
    [2, 0],
    [3, 0]],

   [[0, 1],
    [1, 1],
    [2, 1],
    [3, 1]],

   [[0, 2],
    [1, 2],
    [2, 2],
    [3, 2]],

   [[0, 3],
    [1, 3],
    [2, 3],
    [3, 3]],

   [[0, 4],
    [1, 4],
    [2, 4],
    [3, 4]]])

I can loop over the position and compute the norm of the difference between the goal position and each position of the position matrix like this: 我可以遍历该位置并计算目标位置与位置矩阵的每个位置之间的差的范数,如下所示:

pos_goal = np.array([1,2])
dist_matrix = np.zeros(l_arr.shape[:2])
for i, line in enumerate(l_arr):
    for j, pos in enumerate(line):
        dist_matrix[i,j] = np.linalg.norm(pos - pos_goal) 

dist_matrix

Result: 结果:

array([[ 2.23606798,  2.        ,  2.23606798,  2.82842712],
   [ 1.41421356,  1.        ,  1.41421356,  2.23606798],
   [ 1.        ,  0.        ,  1.        ,  2.        ],
   [ 1.41421356,  1.        ,  1.41421356,  2.23606798],
   [ 2.23606798,  2.        ,  2.23606798,  2.82842712]])

Isn't there a better way to do this (without the 2 loops)? 没有更好的方法(没有2个循环)吗?

The np.linalg.norm function takes an axis argument, so you want: np.linalg.norm函数采用axis参数,因此您需要:

In [6]: np.linalg.norm(l_arr - pos_goal, axis=2)
Out[6]:
array([[ 2.23606798,  2.        ,  2.23606798,  2.82842712],
       [ 1.41421356,  1.        ,  1.41421356,  2.23606798],
       [ 1.        ,  0.        ,  1.        ,  2.        ],
       [ 1.41421356,  1.        ,  1.41421356,  2.23606798],
       [ 2.23606798,  2.        ,  2.23606798,  2.82842712]])

You can just use -1 for "the last" axis: 您可以将-1用作“最后一个”轴:

In [7]: np.linalg.norm(l_arr - pos_goal, axis=-1)
Out[7]:
array([[ 2.23606798,  2.        ,  2.23606798,  2.82842712],
       [ 1.41421356,  1.        ,  1.41421356,  2.23606798],
       [ 1.        ,  0.        ,  1.        ,  2.        ],
       [ 1.41421356,  1.        ,  1.41421356,  2.23606798],
       [ 2.23606798,  2.        ,  2.23606798,  2.82842712]])

Note, I used array-broadcasting to get the differences: 注意,我使用数组广播来获得差异:

In [11]: l_arr - pos_goal
Out[11]:
array([[[-1, -2],
        [ 0, -2],
        [ 1, -2],
        [ 2, -2]],

       [[-1, -1],
        [ 0, -1],
        [ 1, -1],
        [ 2, -1]],

       [[-1,  0],
        [ 0,  0],
        [ 1,  0],
        [ 2,  0]],

       [[-1,  1],
        [ 0,  1],
        [ 1,  1],
        [ 2,  1]],

       [[-1,  2],
        [ 0,  2],
        [ 1,  2],
        [ 2,  2]]])

Generally, learning how to use broadcasting in combination with built-in numpy / scipy vectorized functions is the way to achieve substantial speed improvements. 通常, 学习如何结合内置的numpy / scipy向量化功能使用广播是实现大幅速度提升的方法。

Use scipy.spatial.distance.cdist . 使用scipy.spatial.distance.cdist It requires 2D inputs, so you can do something like this: 它需要2D输入,因此您可以执行以下操作:

from scipy.spatial import distance
dist_matrix = distance.cdist(l_arr.reshape(-1, 2), [pos_goal]).reshape(l_arr.shape[:2])

This is quite succinct, and for large arrays will be faster than a manual approach based on looping or broadcasting. 这非常简洁,对于大型阵列,它比基于循环或广播的手动方法要快。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM