如何为另一个向量中的每个元素获取向量中最接近的元素而不重复?

时间:2014-09-24 10:30:57

标签: r vector

我得到了这个代码,它创建了两个向量,对于a中的每个元素,我希望得到b中最接近的元素:

a = rnorm(100)
b = rnorm(100)
c = vapply(a, function(x) which.min(abs(b - x)), 1)
table(duplicated(c))

FALSE  TRUE 
   61    39 

正如你所看到的,这个方法很快就会提供很多重复,这是正常的,但我不想重复。我想在选择索引后从b删除出现但我不知道如何在vapply下执行此操作。

4 个答案:

答案 0 :(得分:4)

您将获得的最接近的匹配是对矢量进行排序,然后将它们配对。 b上的以下版权应该允许您这样做。

p <- order(b)[order(order(a))] # order on b and then back transform the ordering of a

sum(abs(a-b[p]))
[1] 20.76788

显然,允许重复可以使事情更加紧密:

sum(abs(a-b[c]))
[1] 2.45583

答案 1 :(得分:2)

我相信这是你能得到的最好的:sum(abs(sort(a) - sort(b)))

我正在使用data.table来保留a的原始排序:

require(data.table)

set.seed(1)

a <- rnorm(100)
b <- rnorm(100)

sum(abs(a - b))
sum(abs(sort(a) - sort(b)))

dt <- data.table(a = a, b = b)
dt[, id := .I]

# sort dt by a
setkey(dt, a)

# sort b
dt[, b := sort(b)]

# return to original order
setkey(dt, id)

dt
dt[, sum(abs(a - b))]

与Chase的解决方案相比,此解决方案提供了更好的结果:

dt2 <- as.data.table(foo(a,b))
dt2[, sum(abs(a - bval))]
dt[, sum(abs(a - b))]

结果:

> dt2[, sum(abs(a - bval))]
[1] 24.86731
> dt[, sum(abs(a - b))]
[1] 20.76788

答案 2 :(得分:2)

这是非常糟糕的编程,但可能有效并且是矢量化的......

   a <- rnorm(100)
   b <- rnorm(100)
   #make a copy of b (you'll see why)
   b1<-b
   res<- vapply(a, function(x) {ret<-which.min(abs(b1 - x));b1[ret]<<-NA;return(ret)}, 1)

答案 3 :(得分:1)

这几乎肯定可以通过矢量化来改进,但似乎有效并可能完成工作:

set.seed(1)
a = rnorm(5)
b = rnorm(5)

foo <- function(a,b) {

  out <- cbind(a, bval = NA)

  for (i in seq_along(a)) {
    #which value of B is closest?
    whichB <- which.min(abs(b - a[i]))
    #Assign that value to the bval column
    out[i, "bval"] <- b[whichB]
    #Remove that value of B from being chosen again
    b <- b[-whichB]
  }

  return(out)

}

#In action
foo(a,b)
---
              a       bval
[1,] -0.6264538 -0.8204684
[2,]  0.1836433  0.4874291
[3,] -0.8356286 -0.3053884
[4,]  1.5952808  0.7383247
[5,]  0.3295078  0.5757814