2013-05-05 1 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

+0

Нет, это невозможно. Они также не отсортированы. –

ответ

4

Мне нравится intersect и table s, поэтому ...

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 

EDIT: Если вы действительно хотите, что вектор, хотя, это: as.numeric(rep(names(comtab),comtab)).

+1

+1 - Я бы предложил 'comtab <- c (pmin (tv1 [comvals], tv2 [comvals]))'. Ну, теперь я вижу, что это именно то, что сделал @ Карсон. – flodel

+0

@flodel. Ах, круто. Я не знал об этой функции. – Frank

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 * sort, 2 *% in% и 1 * intersection. Я надеялся, что есть немного умный способ сделать это. –

+0

Ну, вы никогда не говорили об эффективности проблемы, поэтому я предложил это в качестве первой попытки. Но опять же без каких-либо гарантий относительно векторов равной длины или если сортируются векторы или какие-либо другие знания о самих векторах ... ну, вы всегда можете использовать Rcpp, если хотите ускорения ... Но при этом говорится, что это решение, похоже, работает довольно быстро для меня даже с большими векторами. – Dason

+0

Я упомянул эффективность в самом начале вопроса: «Как эффективно ...». Я буду проверять эффективность вашего решения. Благодаря! –

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 

EDIT: обернуть функцию, демонстрируют различные случаи и ускорить за @ комментарий Dason в

+0

Кажется, что не работает с векторами разной длины. – Roland

+0

@ Роланд вы в этом уверены? Кажется, для меня нужны векторы разной длины. Он не будет сортироваться, но он работает для меня. Если я не пробовал достаточно тестовых случаев ... – Dason

+0

Ах, вот для чего явно созданы факторы. +1 – Roland

Смежные вопросы