假设我有 5 个向量:
a <- c(1,2,3)
b <- c(2,3,4)
c <- c(1,2,5,8)
d <- c(2,3,4,6)
e <- c(2,7,8,9)
我知道我可以通过使用Reduce()
with来计算所有它们之间的交集intersect()
,如下所示:
Reduce(intersect, list(a, b, c, d, e))
[1] 2
但是我怎样才能找到至少 2 个向量中常见的元素呢?IE:
[1] 1 2 3 4 8
假设我有 5 个向量:
a <- c(1,2,3)
b <- c(2,3,4)
c <- c(1,2,5,8)
d <- c(2,3,4,6)
e <- c(2,7,8,9)
我知道我可以通过使用Reduce()
with来计算所有它们之间的交集intersect()
,如下所示:
Reduce(intersect, list(a, b, c, d, e))
[1] 2
但是我怎样才能找到至少 2 个向量中常见的元素呢?IE:
[1] 1 2 3 4 8
它比很多人看起来要简单得多。这应该非常有效。
将所有内容放入向量中:
x <- unlist(list(a, b, c, d, e))
查找重复项
unique(x[duplicated(x)])
# [1] 2 3 1 4 8
如果sort
需要。
注意:如果列表元素中可能有重复项(您的示例似乎没有暗示),则替换x
为x <- unlist(lapply(list(a, b, c, d, e), unique))
编辑:由于 OP 对 n >= 2 的更通用的解决方案表示了兴趣,我会这样做:
which(tabulate(x) >= n)
如果数据仅由自然整数(1、2 等)组成,如示例中所示。如果不:
f <- table(x)
names(f)[f >= n]
现在这与 James 解决方案相距不远,但它避免了代价高昂的sort
. 它比计算所有可能的组合要快几英里。
您可以尝试所有可能的组合,例如:
## create a list
l <- list(a, b, c, d)
## get combinations
cbn <- combn(1:length(l), 2)
## Intersect them
unique(unlist(apply(cbn, 2, function(x) intersect(l[[x[1]]], l[[x[2]]]))))
## 2 3 1 4
这是另一种选择:
# For each vector, get a vector of values without duplicates
deduplicated_vectors <- lapply(list(a,b,c,d,e), unique)
# Flatten the lists, then sort and use rle to determine how many
# lists each value appears in
rl <- rle(sort(unlist(deduplicated_vectors)))
# Get the values that appear in two or more lists
rl$values[rl$lengths >= 2]
这是一种计算每个唯一值出现的向量数量的方法。
unique_vals <- unique(c(a, b, c, d, e))
setNames(rowSums(!!(sapply(list(a, b, c, d, e), match, x = unique_vals)),
na.rm = TRUE), unique_vals)
# 1 2 3 4 5 8 6 7 9
# 2 5 3 2 1 2 1 1 1
另一种方法,应用矢量化函数outer
:
L <- list(a, b, c, d, e)
f <- function(x, y) intersect(x, y)
fv <- Vectorize(f, list("x","y"))
o <- outer(L, L, fv)
table(unlist(o[upper.tri(o)]))
# 1 2 3 4 8
# 1 10 3 1 1
上面的输出给出了共享每个重复元素 1、2、3、4 和 8 的向量对的数量。
@rengis 方法的一个变体是:
unique(unlist(Map(`intersect`, cbn[1,], cbn[2,])))
#[1] 2 3 1 4 8
在哪里,
l <- mget(letters[1:5])
cbn <- combn(l,2)
当向量很大时,解决方案duplicated
可能tabulate
会溢出您的系统。在这种情况下,dplyr 可以通过以下代码派上用场
library(dplyr) combination_of_vectors <- c(a, b, c, d, e)
#For more than 1
combination_of_vectors %>% as_tibble() %>% group_by(x) %>% filter(n()>1)
#For more than 2
combination_of_vectors %>% as_tibble() %>% group_by(x) %>% filter(n()>2)
#For more than 3
combination_of_vectors %>% as_tibble() %>% group_by(x) %>% filter(n()>2)
希望它可以帮助某人