【问题标题】:How can I quickly see if any elements of more than 2 vectors are equal in R?如何快速查看 R 中是否有超过 2 个向量的任何元素相等?
【发布时间】:2016-08-21 03:20:23
【问题描述】:

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

假设我有 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?,这似乎是在询问如何识别 each 向量中存在的元素,而不是任何向量中的任何元素是否相等。

【问题讨论】:

  • 是任何特定类型的向量吗?
  • @SeverinPappadeux,就我而言,他们都是int。如果某些向量属于不同类型,我想答案可能会有所不同。
  • 您的代码将any 包装到所有比较中,但我认为这会产生问题,即如果向量的长度不同,%in% 会给出逻辑向量输出,当我们换行时使用any(如您所示),只要在比较中的任何单个元素中有一个TRUE,输出将为TRUE。
  • @akrun,这正是我要找的。但是,我同意知道 which 向量具有匹配的元素可能会有所帮助(如果解决方案可以显示哪些 elements 匹配,则可能会更酷,而无需执行额外的 vec1 %in % vec2 比较,例如)。
  • 我在下面发布了一个解决方案,最后一个选项就是你展示的那个。请检查这是否适合您。另外,如果没有,请考虑使用一些示例和基于示例的预期输出来更新您的帖子

标签: r vector any


【解决方案1】:

如果你把你的向量放在一个列表中,它们会更容易使用:

# 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,第二个元素的第二列也是如此,以此类推。其他TRUEs 表示跨向量匹配。如果长度不一致,它将返回相同信息的嵌套列表而不是矩阵。如果您还是希望有一个嵌套列表,请将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 用于布尔而不是索引。

【讨论】:

  • 我有一种预感,apply 正义联盟的成员之一会化险为夷。谢谢,阿利斯泰尔。
【解决方案2】:

我们可以使用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提到的效率,如果需要,可以使用combnfaster version


另外,combn 可以直接应用于list。因此,vectors 可以放在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

【讨论】:

  • 第二个选项是否独立于第一个用于匹配位置标识?似乎 names(v2) &lt;- names(v1) 可能取决于第一个选项,因为 v1 包含。
  • @DanielFletcher 我不想输入两次names(v1),因为它与第一种情况相同。否则,相同。
  • 我接受了 alistaire 的回答,因为它对我来说感觉最简单。从技术上讲,我们可以争辩说它没有按照问题的要求给出单数 TRUEFALSE。但是,它非常接近,我无法从这个答案中获得 any 选项来为我工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-15
  • 1970-01-01
相关资源
最近更新 更多