如何快速查看R中两个以上向量的任何元素是否相等?

时间:2016-08-21 03:20:24

标签: r vector any

(我希望已经有人问过/已经回答了。如果是这样,抱歉,我找不到答案。)

假设我有6个向量。如何快速检查每个向量的任何元素是否等于所有其他向量的任何元素?

我知道我可以做到以下几点,感觉非常麻烦/史前/容易出错:

any(vec1 %in% vec2, vec1 %in% vec3, vec1 %in% vec4, vec1 %in% vec5, vec1 %in% vec6,
    vec2 %in% vec3, vec2 %in% vec4, vec2 %in% vec5, vec2 %in% vec6,
    vec3 %in% vec4, vec3 %in% vec5, vec3 %in% vec6,
    vec4 %in% vec5, vec4 %in% vec6,
    vec5 %in% vec6)

感谢。

顺便说一下,我检查了How to find common elements from multiple vectors?,这似乎是在询问如何识别每个向量中存在的元素,而不是来自任何向量的任何元素是相等。

2 个答案:

答案 0 :(得分:2)

如果您将矢量放在列表中,他们将更容易使用:

# make sample data
set.seed(47)
x <- replicate(6, rpois(3, 10), simplify = FALSE) 

str(x)
# List of 6
#  $ : int [1:3] 16 12 10
#  $ : int [1:3] 9 10 6
#  $ : int [1:3] 10 14 4
#  $ : int [1:3] 7 6 4
#  $ : int [1:3] 12 8 7
#  $ : int [1:3] 7 11 8

现在使用lapply迭代:

lapply(x, function(y){sapply(x, function(z){y %in% z})})

## [[1]]
##      [,1]  [,2]  [,3]  [,4]  [,5]  [,6]
## [1,] TRUE FALSE FALSE FALSE FALSE FALSE
## [2,] TRUE FALSE FALSE FALSE  TRUE FALSE
## [3,] TRUE  TRUE  TRUE FALSE FALSE FALSE
## 
## [[2]]
##       [,1] [,2]  [,3]  [,4]  [,5]  [,6]
## [1,] FALSE TRUE FALSE FALSE FALSE FALSE
## [2,]  TRUE TRUE  TRUE FALSE FALSE FALSE
## [3,] FALSE TRUE FALSE  TRUE FALSE FALSE
## ...    ...  ...   ...   ...   ...   ...

是每个向量的矩阵,其中行是相应向量的元素,列是列表中的每个向量,值表示该元素是否在该向量中。显然每个都将与自身匹配,因此第一个元素的第一列全部是TRUE,第二个元素的第二列也是如此等。其他TRUE s表示交叉向量匹配。如果长度不一致,它将返回相同信息的嵌套列表而不是矩阵。如果您仍然希望拥有嵌套列表,请将sapply更改为lapply

或者,如果您只想要每个向量的匹配向量,

str(lapply(x, function(y){which(sapply(x, function(z){any(y %in% z)}))}))

## List of 6
##  $ : int [1:4] 1 2 3 5
##  $ : int [1:4] 1 2 3 4
##  $ : int [1:4] 1 2 3 4
##  $ : int [1:5] 2 3 4 5 6
##  $ : int [1:4] 1 4 5 6
##  $ : int [1:3] 4 5 6

其中每个元素仍包含其自身作为匹配项。取出which为布尔代替而不是索引。

答案 1 :(得分:1)

我们可以使用combn查找矢量字符串的组合,获取数据,将其与%in%进行比较,如果需要,还可以使用anyunlist

v1 <- unlist(combn(paste0("vec", 1:6), 2, FUN = function(x) 
             any(get(x[1]) %in% get(x[2])), simplify = FALSE))
names(v1) <- combn(paste0("vec", 1:6), 2, FUN = paste, collapse="-")

正如OP提到的效率,如果需要,可以使用faster version combn

此外,combn可以直接应用于list。因此,vector可以放在list中,然后执行combn

v2 <- combn(mget(paste0("vec", 1:6)), 2, FUN = function(x) any(x[[1]] %in% x[[2]]))
names(v2) <- names(v1)

此外,由于OP正在any包装所有比较。我们也可以用一个any

来完成
any(combn(mget(paste0("vec", 1:6)), 2, FUN = function(x) x[[1]] %in% x[[2]]))

但我不确定这是否是正确的方法。

数据

vec1 <- 1:6
vec2 <- 2:3
vec3 <- 5:7
vec4 <- 6:8
vec5 <- 9:10
vec6 <- 11:12