在R中,如何过滤列表列表?

tfl*_*tre 7 r list filter

根据手册,Filter适用于矢量,它也适用于列表,例如:

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

$c
[1] 3
Run Code Online (Sandbox Code Playgroud)

但是,它不适用于列表列表,例如:

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'
Run Code Online (Sandbox Code Playgroud)

在不使用嵌套循环的情况下过滤列表列表的最佳方法是什么?它也可以是列表清单......

(我尝试使用嵌套lapply,但无法使其工作.)

编辑:在第二个例子中,这是我想要获得的:

list(z1=list(a=1,b=2,c=3))
Run Code Online (Sandbox Code Playgroud)

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

S4M*_*S4M 7

我认为你应该使用:

Filter(function(x){length(x)>0 && x[["b"]] > 1},z)
Run Code Online (Sandbox Code Playgroud)

谓词(您用来过滤 z 的函数)适用于 z 的元素,而不是它们的索引。


42-*_*42- 0

这里没有对美丽的要求,也没有进行深度搜索:

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
Run Code Online (Sandbox Code Playgroud)

编辑:此代码将遍历列表并组装“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) }
Run Code Online (Sandbox Code Playgroud)