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)