【问题标题】:R: find vector in list of vectorsR:在向量列表中查找向量
【发布时间】:2015-03-31 00:10:44
【问题描述】:

我正在使用 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

谁能告诉我,怎么了?

您好, 卢皮

【问题讨论】:

    标签: r list vector find


    【解决方案1】:

    “final_states”是一个“列表”,所以你可以将“状态”转换为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将列表元素转换成一个矩阵,然后检查“状态”和“m1”的“行”是否相同。

    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 你可以试试any(mapply(f1, final_states, list(state)))
    • 我找到了以下解决方案:sum(mapply(...)) > 0
    • @lupi5 是的,有很多方法可以做到这一点。很高兴你找到sum
    • @lupi5 我想list(state) %in% final_states 会给你单人TRUE/FALSE
    【解决方案2】:

    每当我看到一个列表对象时,我首先想到的是lapply。似乎以identical 作为测试并以“状态”作为第二个参数来提供预期的结果:

    > 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
    

    【讨论】:

    • 也是一个不错的解决方案!谢谢你。如果一个或多个条目为真,有没有办法只输出真?喜欢any(lapply(...))
    • 从技术上讲,您可以在最后的代码块中使用any(lapply...),但由于any 从列表到逻辑向量的强制转换,它会引发警告。事实上,sapply 也是强制的,但不会警告你。您的里程可能会因这两个选项中的哪一个更糟而有所不同。做你所做的事情的“安全”方法是使用any(vapply(final_states, identical, state, FUN.VALUE = logical(1))),但这很冗长。
    【解决方案3】:

    如果你只是想判断向量是否在列表中,试试

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

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

    【讨论】:

    • 这是一个很好的单行解决方案。在代码的另一个地方,我必须确定向量的索引。我也可以使用Position() 函数。谢谢;-)
    • @lupi5 - 不客气。还有Find(),返回第一个或者最后一个匹配
    • 我尝试了 %in%lapply 并得到了我认为具有误导性的结果。我认为Position 更类似于which
    • 我也是。由于这会返回第一个或最后一个匹配的位置,它应该安全地检查state 是否在列表中
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-11
    • 2020-09-17
    • 2016-06-11
    相关资源
    最近更新 更多