2013-05-05 128 views
1

如何高效地找到具有重複元素的兩個向量的共同元素?r中有多個元素的向量的公共元素

實施例:
v1 <- c(1, 1, 2, 3, 3, 4)
v2 <- c(1, 1, 1, 3, 4, 5)
commonElements <- c(1, 1, 3, 4)

相交不處理重複元素很好。

+0

兩個矢量的長度是否相等? – sgibb 2013-05-05 19:50:22

+0

不,不能假定。他們也沒有排序。 – 2013-05-05 19:51:25

回答

4

我喜歡intersect and table s,so ...

tv1 <- table(v1) 
tv2 <- table(v2) 
comvals <- intersect(names(tv1),names(tv2)) 
comtab <- apply(rbind(tv1[comvals],tv2[comvals]),2,min) 

的信息仍然存在,但在(我的視圖)一個更好的格式:

> comtab 
1 3 4 
2 1 1 

編輯:如果你真的想要的載體,但是,它的:as.numeric(rep(names(comtab),comtab))

+1

+1 - 我會建議'comtab < - c(pmin(tv1 [comvals],tv2 [comvals]))''。那麼,現在我明白@Carson就是這麼做的。 – flodel 2013-05-05 21:35:52

+0

@ flodel。啊,很酷。我不知道這個功能。 – Frank 2013-05-05 22:21:00

3

我確定有很多方法可以做到這一點,但我選擇了排序並使用rle來獲取值和計數。 table也可能完成相同的任務。

common <- function(v1, v2){ 
    r1 <- rle(sort(v1)) 
    r2 <- rle(sort(v2)) 
    vals <- intersect(r1$values, r2$values) 
    l1 <- r1$lengths[r1$values %in% vals] 
    l2 <- r2$lengths[r2$values %in% vals] 
    rep(vals, pmin(l1, l2)) 
} 

common(v1, v2) 

一些例子

> common(v1, v2) 
[1] 1 1 3 4 
> common(c(1,1), c(3,2,1,3,1)) 
[1] 1 1 
> common(c(1,2,3,2), c(1,2,3)) 
[1] 1 2 3 
+0

它的工作原理,但我需要大量使用這個功能,我有點關心效率。您的解決方案使用:2 * rle,2 *排序,2 *%in%和1 * intersection。我希望有一個聰明的方式來做到這一點。 – 2013-05-05 20:01:13

+0

那麼你從來沒有提到問題的效率,所以我提出這是第一次嘗試。但是再次沒有關於等長向量的保證,或者向量是排序的還是關於向量本身的任何其他知識......好吧,如果你想加快速度,你總是可以使用Rcpp ......但是據說這個解決方案似乎有效對於我來說,即使對於大型矢量而言也相當快 – Dason 2013-05-05 20:11:04

+0

我在問題的開頭提到了效率:「如何高效......」。我將測試您的解決方案的效率。謝謝! – 2013-05-05 20:14:15

4

這裏是另一種選擇:

common <- function(v1, v2) { 
    lvls <- unique(c(v1, v2)) 
    v1a <- factor(v1, levels=lvls) 
    v2a <- factor(v2, levels=lvls) 
    v <- pmin(table(v1a), table(v2a)) 
    as.numeric(rep(names(v), v)) 
} 

common(rep(1:3, 1:3), rep(1:2, 1:2)) 
[1] 1 2 2 

common(rep(c(1,3,5), 1:3), rep(c(5,2), 2)) 
[1] 5 5 

編輯:包的功能,表現出不同的情況下,每個@加快達誠的評論

+0

似乎不適用於不同長度的向量。 – Roland 2013-05-05 20:06:25

+0

@Roland你確定嗎?似乎爲我工作的矢量不同長度。它不會被排序,但它適用於我。除非我沒有嘗試足夠的測試用例... – Dason 2013-05-05 20:08:32

+0

啊,這就是明確創建這些因素的原因。 +1 – Roland 2013-05-05 20:13:04