在向量列表中查找向量

8
我是一名有帮助的助手,以下是您需要翻译的内容:

我正在使用R语言,我的目标是检查给定向量是否在唯一向量列表中。

此列表如下:

final_states <- list(c("x" = 5, "y" = 1),
                 c("x" = 5, "y" = 2),
                 c("x" = 5, "y" = 3),
                 c("x" = 5, "y" = 4),
                 c("x" = 5, "y" = 5),
                 c("x" = 3, "y" = 5))

现在我想检查一个给定的状态是否在列表中。例如:
state <- c("x" = 5, "y" = 3)

正如您所看到的,向量状态是列表final_states的一个元素。我的想法是使用%in%运算符进行检查:

state %in% final_states

但是我得到了这个结果:
[1] FALSE FALSE

有人能告诉我,出了什么问题吗?

问候,lupi

3个回答

11

如果您只想确定向量是否在列表中,请尝试

Position(function(x) identical(x, state), final_states, nomatch = 0) > 0
# [1] TRUE

Position()基本上像match()一样工作,但是在列表上。如果您设置nomatch = 0并检查Position > 0,则会得到一个逻辑结果,告诉您state是否在final_states中。


这是一个很好的解决方案,只需一行代码。在代码的另一个位置,我需要确定向量的索引。我也可以使用Position()函数。谢谢;-) - lupi5
@lupi5 - 不用谢。还有Find()函数,它可以返回第一个或最后一个匹配项。 - Rich Scriven
我尝试使用lapply%in%,但结果似乎有误导性。我认为Position更类似于which - IRTFM
我也是。由于这会返回第一个或最后一个匹配项的位置,因此它可以安全地检查 state 是否在列表中。 - Rich Scriven

8
"final_states" 是一个 "列表(list)",所以您可以将 "state" 转换为 list,然后执行。
final_states %in% list(state)
#[1] FALSE FALSE  TRUE FALSE FALSE FALSE

或者使用mapply检查"state"中的所有元素是否都存在于"final_states"的每个列表元素中(假设向量和列表元素的长度相同)

 f1 <- function(x,y) all(x==y)
 mapply(f1, final_states, list(state))
 #[1] FALSE FALSE  TRUE FALSE FALSE FALSE

或将列表元素 rbind 到矩阵中,然后检查 "state" 和 "m1" 的 "rows" 是否相同。

m1 <- do.call(rbind, final_states)
!rowSums(m1!=state[col(m1)])
#[1] FALSE FALSE  TRUE FALSE FALSE FALSE

或者

 m1[,1]==state[1] & m1[,2]==state[2]
 #[1] FALSE FALSE  TRUE FALSE FALSE FALSE

更新

如果您需要获取单个的TRUE/FALSE

  any(mapply(f1, final_states, list(state)))
  #[1] TRUE

或者

  any(final_states %in% list(state))
  #[1] TRUE

或者

 list(state) %in% final_states
 #[1] TRUE

或者使用来自 "fastmatch" 的 "更快" 的 fmatch。
 library(fastmatch)
 fmatch(list(state), final_states) >0
 #[1] TRUE

基准测试

@Richard Sciven的base R函数与其他解决方案相比非常快,除了使用fmatch的解决方案。

 set.seed(295)
 final_states <- replicate(1e6, sample(1:20, 20, replace=TRUE), 
          simplify=FALSE)
 state <- final_states[[151]]


 richard <- function() {Position(function(x) identical(x, state),
              final_states, nomatch = 0) > 0}
 Bonded <- function(){any( sapply(final_states, identical, state) )}
 akrun2 <- function() {fmatch(list(state), final_states) >0}
 akrun1 <- function() {f1 <- function(x,y) all(x==y)
            any(mapply(f1, final_states, list(state)))}

 library(microbenchmark)
 microbenchmark(richard(), Bonded(), akrun1(), akrun2(), 
        unit='relative', times=20L)
 #Unit: relative
 #    expr          min           lq        mean      median          uq
 # richard()     35.22635     29.47587    17.49164    15.66833    14.58235
 # Bonded() 109440.56885 101382.92450 55252.86141 47734.96467 44289.80309
 # akrun1() 167001.23864 138812.85016 75664.91378 61417.59871 62667.94867
 # akrun2()      1.00000      1.00000     1.00000     1.00000     1.00000
  #          max neval cld
  #     14.62328    20 a  
  #  46299.43325    20 b 
  #  63890.68133    20 c
  #      1.00000    20 a  

有没有一种简单的OR方法来评估结果布尔向量?我想到了类似于or(mapply(f1, final_states, list(state))) => TRUE这样的东西。 - lupi5
@lupi5 你可以尝试使用 any(mapply(f1, final_states, list(state))) - akrun
我找到了以下解决方案:sum(mapply(...)) > 0。 - lupi5
@lupi5 是的,有很多方法可以实现这个功能。很高兴你找到了“sum”。 - akrun
1
@lupi5 我认为 list(state) %in% final_states 可以得到一个单一的 TRUE/FALSE - akrun
谢谢你详细的回答,akrun!我学到了很多。特别是使用简单的 list(state) %in% final_states 和快速的 fmatch() 函数的解决方案非常有趣。 - lupi5

3
每当我看到一个列表对象时,我首先想到的是使用lapply。它似乎能够通过identical测试并将'state'作为第二个参数返回预期结果:
> lapply(final_states, identical, state)
[[1]]
[1] FALSE

[[2]]
[1] FALSE

[[3]]
[1] TRUE

[[4]]
[1] FALSE

[[5]]
[1] FALSE

[[6]]
[1] FALSE

使用以下命令可获得可能有用的中间结果:
lapply(final_states, match, state)

...但是它返回一系列位置向量,其中c(1,2)是正确的结果。

如果您想要结果作为向量返回,比如说您想使用any,那么请使用sapply而不是lapply

> any( sapply(final_states[-3], identical, state) )
[1] FALSE
> any( sapply(final_states, identical, state) )
[1] TRUE

还有一个不错的解决方案!谢谢。如果有一个或多个条目为TRUE,是否有一种方法只输出TRUE?像any(lapply(...))这样的方式? - lupi5
在代码的最后一个块中,你理论上可以使用 any(lapply...),但是它会因为 any 将列表转换成逻辑向量而抛出警告。实际上,sapply 也在进行强制类型转换,但没有警告你。对于这两个选项,哪一种更糟取决于你的具体情况。做这件事的“安全”方法是使用 any(vapply(final_states, identical, state, FUN.VALUE = logical(1))),但这样比较啰嗦。 - J. Mini

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接