R编程:在2个数组(包括重复数据)中找到共同元素的最快方法?

时间:2014-07-23 16:18:20

标签: r

我想在2个数组中找到共同的元素(包括重复元素)。哪个是实现这个目标的最快方法? (只要速度快,我不介意使用包装)

[我已经检查过intersect()但它不包含重复项]

[我现在使用的代码是 -

commonelements <- function(a, b) {

test <- c(a,b)
test <- test[duplicated(test)]
test[duplicated(test)]
}

有什么方法可以让它更快?我可能要调用这个函数数百万次。 ]

实施例, 阵列&#39; A&#39; =(1,2,2,2,3,4) 阵列&#39; B&#39; =(1,2,2,4,5,6)

我想得到一个阵列&#39; C&#39; =(1,2,2,4)

[注意:数组并不总是排序]

[编辑:我并没有特别关注数组中元素的顺序&#39; C&#39;。我只需要数组的长度&#39; C&#39;]

3 个答案:

答案 0 :(得分:2)

我不确定它是否是最快的,但这可以完成工作。

my.array <- array(1:24, dim=c(3,4,2))
my.array2 <- array(5:28, dim=c(3,4,2))
my.array[my.array%in%my.array2]

答案 1 :(得分:1)

在许多评论和预期输出的一些澄清之后编辑:

A <- c(1,2,2,2,3,4)
B <- c(1,2,2,4,5,6)

unlist(sapply(intersect(A, B), function(x) rep(x, min(sum(B == x), sum(A == x)))))
#[1] 1 2 2 4

并使其成为问题中的函数(根据最新编辑,只需要输出的长度):

commonelements <- function(A, B){
   length(unlist(sapply(intersect(A, B), function(x) rep(x, min(sum(B == x), sum(A == x))))))
}

commonelements(A, B)
[1] 4

基准

set.seed(2014)

A <- sample(1:20, 100, TRUE)
B <- sample(1:20, 100, TRUE)

baptiste <- function(A, B) {
  a <- as.data.frame.table(table(A))
  b <- as.data.frame.table(table(B))

  coincidences <- merge(a, b, by.x="A", by.y="B")
  rle <- structure(list(lengths=apply(coincidences[,-1], 1, min),
                        values = as.numeric(coincidences[,1])), 
                   class="rle")
  return(inverse.rle(rle))
}

beginner <- function(A, B){
  unlist(sapply(intersect(A, B), function(x) rep(x, min(sum(B == x), sum(A == x)))))
}

library(microbenchmark)

microbenchmark(baptiste(A, B), beginner(A, B), times = 50, unit = "relative")

Unit: relative
          expr     min      lq  median       uq      max neval
baptiste(A, B) 13.9784 12.4557 11.5562 11.71972 60.71423    50
beginner(A, B)  1.0000  1.0000  1.0000  1.00000  1.00000    50

答案 2 :(得分:1)

也许是这样的,

A = c(1,2,2,2,3,4)
B = c(1,2,2,4,5,6)


a <- as.data.frame.table(table(A))
b <- as.data.frame.table(table(B))

coincidences <- merge(a, b, by.x="A", by.y="B")
rle <- structure(list(lengths=apply(coincidences[,-1], 1, min),
               values = as.numeric(coincidences[,1])), 
               class="rle")
inverse.rle(rle)

更大样本的时间(改编自beginneR)

A <- sample(1:2000, 100000, TRUE)
B <- sample(1:2000, 100000, TRUE)

Unit: relative
           expr      min       lq   median       uq      max neval
 baptiste(A, B)  1.00000  1.00000  1.00000  1.00000  1.00000    50
 beginner(A, B) 23.08864 22.23251 21.65671 20.82651 13.88881    50