【问题标题】:For loop on two arrays of points在两个点数组上循环
【发布时间】:2024-01-06 07:28:01
【问题描述】:

我有两个点数组:list1list1.shape = [N, 3]list2list2。形状 = [M, 3]N,M内:点的总数,(x,y,z)是3D中的3个坐标。

现在我想检查 list1 的每个点是否与 list2 的每个点都在 r 的距离内。执行此操作的一种自然方法是 for 循环:

for i in range(N):
    for j in range(M):
        if (list1[i, 0] - list2[j, 0])**2 + (list1[i, 1] - list2[j, 1])**2 + (list1[i, 2] - list2[j, 2])**2 < r**2:
        ''' Return 1 if list1[i] is within list2[j] '''
            return True
        else:
        ''' Return 0 if list1[i] is not within list2[j] '''
            return False

但是速度太慢了。我可以做更有效的方法吗?

【问题讨论】:

  • 可能k-d树是解决方案? en.wikipedia.org/wiki/K-d_tree
  • 我尝试使用 scipy 的 KdTree,但速度并不快。
  • 欧几里得距离矩阵的最佳解决方案在这个问题中:*.com/questions/3518574/…。用 list1 替换一个“数据”,用 list2 替换另一个
  • 您的代码会多次覆盖a[i],只有j==M-1 的值才重要。您实际上需要它如何表现?
  • 抱歉弄错了,我修改了。

标签: python arrays performance for-loop euclidean-distance


【解决方案1】:

您可以使用外部运算来计算距离矩阵而无需 for 循环:

s = np.subtract.outer

d_matrix = s(list1[:,0], list2[:,0])**2
d_matrix += s(list1[:,1], list2[:,1])**2
d_matrix += s(list1[:,2], list2[:,2])**2

其中每条线是点 i 到所有点的距离。要使用您的标准找出点 i 是否接近任何点:

a = np.zeros_like(list1[:,0])
a[np.any(d_matrix < r**2, axis=1)] = 1

【讨论】:

  • @user2863620 但你应该在 K-d Tree 中尝试一下,因为它只计算 d_matrix 的上三角形,因此效率更高(如果需要)
  • 用M,N小。 Kd-Tree 似乎并不比蛮力方式快。