urgeo
urgeo

Reputation: 641

python: finding smallest distance between two points in two arrays

I've got two lists containing a series of tuples (x,y), representing different points on a Cartesian plane:

a = [(0, 0), (1, 2), (1, 3), (2, 4)]
b = [(3, 4), (4, 1), (5, 3)]

I'd like to find the two points (one for each list, not within the same list) at the smaller distance, in this specific case:

[((2, 4), (3, 4))]

whose distance is equal to 1. I was using list comprehension, as:

[(Pa, Pb) for Pa in a for Pb in b \
if math.sqrt(math.pow(Pa[0]-Pb[0],2) + math.pow(Pa[1]-Pb[1],2)) <= 2.0]

but this uses a threshold value. Is there a way to append an argmin() somewhere or something like that and get only the pair [((xa, ya), (xb, yb))] smallest distance? Thanks.

Upvotes: 1

Views: 3553

Answers (4)

Kramer84
Kramer84

Reputation: 47

You could also use the scipy.spatial library with the following :

import scipy.spatial as spspat
import numpy as np
distanceMatrix = spspat.distance_matrix(a,b)
args = np.argwhere(distanceMatrix==distanceMatrix.min())
print(args)

This will return you the following : array([[3, 0]]) , being the position of the points in each list. This should also work in any dimension.

Upvotes: 0

MaxU - stand with Ukraine
MaxU - stand with Ukraine

Reputation: 210842

Solution similar to DevShark's one with a few optimization tricks:

import math
import itertools
import numpy as np

def distance(p1, p2):
    return math.hypot(p2[0] - p1[0], p2[1] - p1[1])

a = [(0, 0), (1, 2), (1, 3), (2, 4)]
b = [(3, 4), (4, 1), (5, 3)]

points = [tup for tup in itertools.product(a, b)]

print(points[np.argmin([distance(Pa, Pb) for (Pa, Pb) in points])])

Upvotes: 1

DevShark
DevShark

Reputation: 9112

import numpy
e = [(Pa, Pb) for Pa in a for Pb in b]
e[numpy.argmin([math.sqrt(math.pow(Pa[0]-Pb[0],2) + math.pow(Pa[1]-Pb[1],2)) for (Pa, Pb) in e])]

Will use argmin as you suggested and return ((2, 4), (3, 4))

Upvotes: 1

mvelay
mvelay

Reputation: 1520

Just use list comprehension and min as follows:

dist = [(Pa, Pb, math.sqrt(math.pow(Pa[0]-Pb[0],2) + math.pow(Pa[1]-Pb[1],2)))
        for Pa in a for Pb in b]

print min(dist, key=lambda x:x[2])[0:2]

Upvotes: 1

Related Questions