List 在R中,如何筛选列表列表?

List 在R中,如何筛选列表列表?,list,r,filter,List,R,Filter,根据手册,它对向量起作用,同时也对列表起作用,例如: z <- list(a=1, b=2, c=3) Filter(function(i){ z[[i]] > 1 }, z) $b [1] 2 $c [1] 3 z <- list(z1=list(a=1,b=2,c=3), z2=list(a=1,b=1,c=1), z3=list()) Filter(function(i){ if(length(z[[i]])>0){ if(z[[i]]$b &g

根据手册,它对向量起作用,同时也对列表起作用,例如:

z <- list(a=1, b=2, c=3)
Filter(function(i){
  z[[i]] > 1
}, z)
$b
[1] 2

$c
[1] 3
z <- list(z1=list(a=1,b=2,c=3), z2=list(a=1,b=1,c=1), z3=list())
Filter(function(i){
  if(length(z[[i]])>0){
    if(z[[i]]$b > 1)
      TRUE
    else
      FALSE
  }
  else
    FALSE
}, z)
Error in z[[i]] : invalid subscript type 'list'

也就是说,没有z$z2是因为z$z2$b<1,没有z$z3是因为它是空的。

这里没有美感,也没有深度搜索:

z2 <- lapply(z, function(x){ if( "b" %in% names(x) && x[["b"]] >1 ) x else {}   } )
z2[unlist(lapply(z2, is.null))] <- NULL

> z2
$z1
$z1$a
[1] 1

$z1$b
[1] 2

$z1$c
[1] 3
z21)x else{})
z2[unlist(lappy(z2,is.null))]z2
$z1
$z1$a
[1] 1
$z1$b
[1] 2
$z1$c
[1] 3
编辑:这段代码将遍历一个列表并组装具有'b'>1的节点。需要做一些工作来正确标记节点。首先是嵌套更深的列表:

z <- list(z1=list(a=1,b=2,c=3), z2=list(a=1,b=1,c=1), z3=list(),
          z4 = list(z5=list(a=5,b=6,c=7), z6=list(a=7,b=8,c=9)))

checkbGT1 <- function(ll){ root <- list()
             for(i in seq_along(ll) ) {if ("b" %in% names(ll[[i]]) && ll[[i]]$b >1) {
                                 root <- c(root, ll[[i]]) 
                                 }else{ 
                                 if(  length(ll[[i]]) && is.list(ll[[i]]) ) 
                                    { root <- c(root, list(checkbGT1( ll[[i]] ))) }
                                          } 
                                       } 
                  return(root) }

z在你提问之前,我从未使用过
Filter
,所以这是早上第一件事的一个很好的练习:)

至少有几件事让你感到困惑(我想)

让我们从您的第一个简单匿名函数开始,但让我们将其独立起来,以便更易于阅读:

f <- function(i){
        z[[i]] > 1
     }
您将看到,
Filter
将实际针对列表列表运行:

 z <- list(z1=list(a=1,b=2,c=3), z2=list(a=1,b=1,c=1))
 Filter( f, z)

您可能需要添加一些逻辑来清理输出,以便
FALSE
结果不会被干扰到
numeric(0)
。显然,我只使用了一个简单的函数,而不是第二个例子中使用的更复杂的函数

我认为你应该使用:

Filter(function(x){length(x)>0 && x[["b"]] > 1},z)
谓词(用于筛选z的函数)应用于z的元素,而不是它们的索引。

按键筛选子列表。 写在阅读的答案,帮助我

zall<-list(z1=list(list(key=1,b=2,c=3),list(key=2,b=3,c=4)))
zall
#> $z1
#> $z1[[1]]
#> $z1[[1]]$key
#> [1] 1
#> 
#> $z1[[1]]$b
#> [1] 2
#> 
#> $z1[[1]]$c
#> [1] 3
#> 
#> 
#> $z1[[2]]
#> $z1[[2]]$key
#> [1] 2
#> 
#> $z1[[2]]$b
#> [1] 3
#> 
#> $z1[[2]]$c
#> [1] 4
lapply(zall$z1, function(x){ x[intersect(names(x),"key")]  } )
#> [[1]]
#> [[1]]$key
#> [1] 1
#> 
#> 
#> [[2]]
#> [[2]]$key
#> [1] 2
lapply(zall$z1, function(x){ x[setdiff(names(x),"key")]  } )
#> [[1]]
#> [[1]]$b
#> [1] 2
#> 
#> [[1]]$c
#> [1] 3
#> 
#> 
#> [[2]]
#> [[2]]$b
#> [1] 3
#> 
#> [[2]]$c
#> [1] 4
zall$z1
#>$z1[[1]]
#>$z1[[1]]$key
#> [1] 1
#> 
#>$z1[[1]]$b
#> [1] 2
#> 
#>$z1[[1]]$c
#> [1] 3
#> 
#> 
#>$z1[[2]]
#>$z1[[2]]$key
#> [1] 2
#> 
#>$z1[[2]]$b
#> [1] 3
#> 
#>$z1[[2]]$c
#> [1] 4
lapply(zall$z1,函数(x){x[相交(名称(x),“键”)]})
#> [[1]]
#>[[1]]$key
#> [1] 1
#> 
#> 
#> [[2]]
#>[[2]]$key
#> [1] 2
lapply(zall$z1,函数(x){x[setdiff(名称(x),“键”)]})
#> [[1]]
#>[1]]$b
#> [1] 2
#> 
#>[[1]]$c
#> [1] 3
#> 
#> 
#> [[2]]
#>[2]]$b
#> [1] 3
#> 
#>[[2]]$c
#> [1] 4

这个问题的现代解决方案是:

library(tidyverse)
z <- list(z1=list(a=1,b=2,c=3), z2=list(a=1,b=1,c=1), z3=list())

注意,这现在非常灵活,并且可以轻松地进行其他筛选,例如,如果a==1

@Iterator:是的,谢谢,但我无法获得我想要的输出(请参见我的编辑)。这很奇怪:其他人在这里发布了答案,现在答案不见了。我不知道它解决了什么问题。列表是向量,只是不是原子vectors@Iterator-那是我。把问题读得太快;OP希望将每个组件列表视为一个单元,并根据某些条件返回或不返回
Rappy
(我想)直接深入到每个嵌套列表的每个单独元素。我不熟悉这个函数,但向量可以是表(矩阵)的索引或向量列表的索引,而向量列表又是列表对象的索引。拥有嵌套列表并不是什么大问题。我经常使用索引查找来引用参数表或更复杂的索引。如果表的宽度设置为嵌套的最深长度,那么所有不太浅的条目在表中都可以有1的平凡索引。谢谢,您的解决方案适用于我提供的示例,但对于列表列表列表等,它不容易扩展。无论如何,如果没有更好的答案,我接受你的回答。我认为递归回答是可能的。我甚至可以复制这样一个答案的结构,但是我很难填充节点。我会等的。非常感谢!我设法在两级列表上使用了你的答案的精巧版本,但在三级列表上却不起作用。结果,我得到一个空的“命名列表”,我不知道那是什么。。。但这不允许我问一个新问题。我应该先接受你的回答吗?
fancyFilter <- function(f, x){
  if ( is.list( x[[1]] ) ) #only testing the first element... bad practice
    lapply( x, fancyFilter, f=f ) #recursion FTW!!
  else
    return( lapply(x, Filter, f=f ) )
}
> fancyFilter(f, z)
$z1
$z1$a
numeric(0)

$z1$b
[1] 2

$z1$c
[1] 3


$z2
$z2$a
numeric(0)

$z2$b
numeric(0)

$z2$c
numeric(0)
Filter(function(x){length(x)>0 && x[["b"]] > 1},z)
zall<-list(z1=list(list(key=1,b=2,c=3),list(key=2,b=3,c=4)))
zall
#> $z1
#> $z1[[1]]
#> $z1[[1]]$key
#> [1] 1
#> 
#> $z1[[1]]$b
#> [1] 2
#> 
#> $z1[[1]]$c
#> [1] 3
#> 
#> 
#> $z1[[2]]
#> $z1[[2]]$key
#> [1] 2
#> 
#> $z1[[2]]$b
#> [1] 3
#> 
#> $z1[[2]]$c
#> [1] 4
lapply(zall$z1, function(x){ x[intersect(names(x),"key")]  } )
#> [[1]]
#> [[1]]$key
#> [1] 1
#> 
#> 
#> [[2]]
#> [[2]]$key
#> [1] 2
lapply(zall$z1, function(x){ x[setdiff(names(x),"key")]  } )
#> [[1]]
#> [[1]]$b
#> [1] 2
#> 
#> [[1]]$c
#> [1] 3
#> 
#> 
#> [[2]]
#> [[2]]$b
#> [1] 3
#> 
#> [[2]]$c
#> [1] 4
library(tidyverse)
z <- list(z1=list(a=1,b=2,c=3), z2=list(a=1,b=1,c=1), z3=list())
tibble(disc = z, Names = names(z)) %>% 
  hoist(disc, c = "c") %>%
  filter(c == 3) %>%
  unnest_wider(disc) %>% 
  split(.$Names) %>% map(select, -Names) %>% 
  map(as.list)