2

我正在实现一个简单的代码,它计算一个点和所有点之间的距离(x_a, y_a),并返回找到的最小距离。对 中的所有点重复此操作。list_A(x_b, y_b)list_Blist_A

我的MWE代码之一:

# list_A points defined in array.
list_A = np.array([
    [x_data_a,  # x
     y_data_a]  # y
    ], dtype=float)

# list_B points defined in list.
list_B = [[x_data_b], [y_data_b]]

# Iterate through all data points in list_A
for ind, x_a in enumerate(list_A[0][0]):
    y_a = list_A[0][1][ind]

    # Iterate through all points in list_B.
    dist_min = 1000.
    for ind2, x_b in enumerate(list_B[0]):
        y_b = list_B[1][ind2]
        # Find distance between points.
        dist = (x_a-x_b)**2 + (y_a-y_b)**2
        if dist < dist_min:
            # Update value of min distance.
            dist_min = dist

    print 'Min dist to (', x_a, y_a, '): ', dist_min

数据格式如下:

list_A = [[[1.2 2.3 1.5 2.3 5.8 4.6 9.1] [2.5 1.0 4.6 2.4 7.4 1.1 3.2]]]

list_B = [[1.4, 5.8, 7.9], [6.1, 1.2, 3.7]]

对于大列表/数组,这可能需要相当长的时间才能完成。这可以加速吗?

4

3 回答 3

2

运行您的代码,我获得以下信息:

Min dist to ( 1.2 2.5 ):  13.0
Min dist to ( 2.3 1.0 ):  12.29
Min dist to ( 1.5 4.6 ):  2.26
Min dist to ( 2.3 2.4 ):  13.69
Min dist to ( 5.8 7.4 ):  18.1
Min dist to ( 4.6 1.1 ):  1.45
Min dist to ( 9.1 3.2 ):  1.69

将您的数组转换为以下 Nx2 数组:

a
[[ 1.2  2.5]
 [ 2.3  1. ]
 [ 1.5  4.6]
 [ 2.3  2.4]
 [ 5.8  7.4]
 [ 4.6  1.1]
 [ 9.1  3.2]]

b
[[ 1.4  6.1]
 [ 5.8  1.2]
 [ 7.9  3.7]]

现在以下应该可以工作:

import scipy.spatial.distance as spdist

dist_arr = spdist.cdist(a,b)

print dist_arr**2
[[ 13.    22.85  46.33]
 [ 26.82  12.29  38.65]
 [  2.26  30.05  41.77]
 [ 14.5   13.69  33.05]
 [ 21.05  38.44  18.1 ]
 [ 35.24   1.45  17.65]
 [ 67.7   14.89   1.69]]

ind = np.argmin(dist_arr,axis=1)

print ind
[0 1 0 1 2 1 2]

print dist_arr[np.arange(ind.shape[0]),ind]**2
[ 13.    12.29   2.26  13.69  18.1    1.45   1.69]

a如果和b是 2X5000 与原始代码约 135 秒,则需要 ~.3 秒。加速 450 倍。

于 2013-09-22T19:49:39.630 回答
1

如果您想避免使用 scipy 获取 scipy.spatial.dist

import numpy as np

a = np.random.rand(2,1000) 
b = np.random.rand(2,1001)

min_dist = np.sqrt(np.min([np.min(np.sum((b - a[:,i,None])**2, axis=0)) 
                           for i in range(a.shape[1])]))

如果您正在寻找 a 中每个点的 min dist,则将最后一行替换为

min_dists = np.sqrt([np.min(np.sum((b - a[:,i,None])**2, axis=0)) 
                           for i in range(a.shape[1])])
于 2013-09-22T20:01:04.980 回答
1

使用scipy.spatial.distance.cdist并且您根本不需要编写自己的距离计算代码。

编辑:您需要转置您的数据。它应该是这样的格式:

list_A = [
 [1, 2],
 [3, 4],
 [4, 5]
]

list_B = [
 [8, 9],
 [10, 11],
 [11, 12],
 [13, 14]
]

目前,您拥有的是 X 坐标列表和单独的 Y 坐标列表。您需要重新调整它们的方向,以便拥有一个 XY 对列表。如果您的数据是普通列表,您可以使用list_A = zip(*list_A); 如果它们是 numpy 数组,您可以使用list_A = list_A.T.

于 2013-09-22T19:42:16.350 回答