方法 1
您可以使用广播来获取距离矩阵:
>>> data = np.array([2,9,5,6,55,8])
>>> dst_matrix = data - data[:, None]
>>> dst_matrix
array([[ 0, 7, 3, 4, 53, 6],
[ -7, 0, -4, -3, 46, -1],
[ -3, 4, 0, 1, 50, 3],
[ -4, 3, -1, 0, 49, 2],
[-53, -46, -50, -49, 0, -47],
[ -6, 1, -3, -2, 47, 0]])
然后我们可以按照in this post的建议消除对角线:
dst_matrix = dst_matrix[~np.eye(dst_matrix.shape[0],dtype=bool)].reshape(dst_matrix.shape[0],-1)
>>> dst_matrix
array([[ 7, 3, 4, 53, 6],
[ -7, -4, -3, 46, -1],
[ -3, 4, 1, 50, 3],
[ -4, 3, -1, 49, 2],
[-53, -46, -50, -49, -47],
[ -6, 1, -3, -2, 47]])
终于可以找到最少的物品了:
>>> np.min(np.abs(dst_matrix), axis=1)
array([ 3, 1, 1, 1, 46, 1])
方法 2
如果您正在寻找节省时间和内存的解决方案,最好的选择是scipy.spatial.cKDTrees,它将点(任何维度)打包到针对查询最近点进行优化的特定数据结构中。它还可以扩展到 2D 或 3D。
import scipy.spatial
data = np.array([2,9,5,6,55,8])
ckdtree = scipy.spatial.cKDTree(data[:,None])
distances, idx = ckdtree.query(data[:,None], k=2)
output = distances[:,1] #distances to not coincident points
对于每个点,这里需要查询前两个最近的点,因为它们中的第一个预计是重合的。这是我在所有建议的答案之间找到的唯一解决方案,不需要很长时间(1M 点的平均性能是 4 秒)。 警告:您需要在应用此方法之前过滤重复点。