Minimum Euclidean distance between points in two different Numpy arrays, not within Minimum Euclidean distance between points in two different Numpy arrays, not within numpy numpy

Minimum Euclidean distance between points in two different Numpy arrays, not within


(Months later)scipy.spatial.distance.cdist( X, Y )gives all pairs of distances,for X and Y 2 dim, 3 dim ...
It also does 22 different norms, detailedhere .

# cdist example: (nx,dim) (ny,dim) -> (nx,ny)from __future__ import divisionimport sysimport numpy as npfrom scipy.spatial.distance import cdist#...............................................................................dim = 10nx = 1000ny = 100metric = "euclidean"seed = 1    # change these params in sh or ipython: run this.py dim=3 ...for arg in sys.argv[1:]:    exec( arg )np.random.seed(seed)np.set_printoptions( 2, threshold=100, edgeitems=10, suppress=True )title = "%s  dim %d  nx %d  ny %d  metric %s" % (        __file__, dim, nx, ny, metric )print "\n", title#...............................................................................X = np.random.uniform( 0, 1, size=(nx,dim) )Y = np.random.uniform( 0, 1, size=(ny,dim) )dist = cdist( X, Y, metric=metric )  # -> (nx, ny) distances#...............................................................................print "scipy.spatial.distance.cdist: X %s Y %s -> %s" % (        X.shape, Y.shape, dist.shape )print "dist average %.3g +- %.2g" % (dist.mean(), dist.std())print "check: dist[0,3] %.3g == cdist( [X[0]], [Y[3]] ) %.3g" % (        dist[0,3], cdist( [X[0]], [Y[3]] ))# (trivia: how do pairwise distances between uniform-random points in the unit cube# depend on the metric ? With the right scaling, not much at all:# L1 / dim      ~ .33 +- .2/sqrt dim# L2 / sqrt dim ~ .4 +- .2/sqrt dim# Lmax / 2      ~ .4 +- .2/sqrt dim


To compute the m by p matrix of distances, this should work:

>>> def distances(xy1, xy2):...   d0 = numpy.subtract.outer(xy1[:,0], xy2[:,0])...   d1 = numpy.subtract.outer(xy1[:,1], xy2[:,1])...   return numpy.hypot(d0, d1)

the .outer calls make two such matrices (of scalar differences along the two axes), the .hypot calls turns those into a same-shape matrix (of scalar euclidean distances).


The accepted answer does not fully address the question, which requests to find the minimum distance between the two sets of points, not the distance between every point in the two sets.

Altough a straightforward solution to the original question indeed consists of computing the distance between every pair and susequently finding the minimum one, this is not necessary if one is only interested in the minimum distances. A much faster solution exists for the latter problem.

All the proposed solutions have a running time that scales as m*p = len(xy1)*len(xy2). This is OK for small datasets, but an optimal solution can be written that scales as m*log(p), producing huge savings for large xy2 datasets.

This optimal execution time scaling can be achieved using scipy.spatial.cKDTree as follows

import numpy as npfrom scipy import spatialxy1 = np.array(    [[243,  3173],     [525,  2997]])xy2 = np.array(    [[682, 2644],     [277, 2651],     [396, 2640]])# This solution is optimal when xy2 is very largetree = spatial.cKDTree(xy2)mindist, minid = tree.query(xy1)print(mindist)# This solution by @denis is OK for small xy2mindist = np.min(spatial.distance.cdist(xy1, xy2), axis=1)print(mindist)

where mindist is the minimum distance between each point in xy1 and the set of points in xy2