user7064
user7064

Reputation: 217

R: smallest distance between an element of vector a and an element of vector b

a and b are two vectors of real numbers.

They do not necessarily have the same length.

The distance between the ith element of a and the jth element of b is defined as abs(a[i] - b[j])

How would you compute the smallest distance between any element of a and any element of b without explicit loops?

Here is what I did: min(sapply(X=1:length(b), FUN=function(x) abs(a - b[x]))).

However, I have the feeling there is something better to do...

Upvotes: 3

Views: 6150

Answers (3)

Paul Hiemstra
Paul Hiemstra

Reputation: 60924

I'd use the dist function to create a distance matrix, and then find the minimum distance in that. This is probably much faster than an explicit loop in R (including sapply).

a = runif(23)
b = runif(10)
d_matrix = as.matrix(dist(cbind(a,b)))
d_matrix[d_matrix == 0] <- NA
sqrt(min(d_matrix, na.rm = TRUE))

Note that cbind recycles the smaller vector. So this function is probably not optimal, but for vectors that do not differ that much in size still much fast than an explicit loop.

And to find which pair of elements had this distance (although the recycling introduces some challenges here):

which(d_matrix == min(d_matrix, na.rm = TRUE), arr.ind = TRUE)

Upvotes: 4

Hong Ooi
Hong Ooi

Reputation: 57686

One-liner should work here: min(abs(outer(a, b, "-")))

Upvotes: 2

thelatemail
thelatemail

Reputation: 93803

Here's an attempt:

a <- c(9,5,6); b <- c(6,9)
# a
#[1] 9 5 6
# b
#[1] 6 9

combos <- sapply(b,function(x) abs(x-a))
# or an alternative
combos <- abs(outer(a,b,FUN="-"))

You could then get the minimum distance with:

min(combos)

If you wanted to get the respective indexes of the minimum values you could do:

which(combos==min(combos),arr.ind=TRUE)

# each matrix row has the 2 indexes for the minimums
# first column is 'a' index, second is 'b' index
#      row col
# [1,]   3   1
# [2,]   1   2

Upvotes: 3

Related Questions