开发者

Subset elements in a list based on a logical condition

How can I subset a list based on a condition (TRUE, FALSE) in another list? Please, see my example below:

l <- list(a=c(1,2,3), b=c(4,5,6,5), c=c(3,4,5,6))
l
$a
[1]开发者_如何学C 1 2 3

$b
[1] 4 5 6 5

$c
[1] 3 4 5 6

cond <- lapply(l, function(x) length(x) > 3)
cond
$a
[1] FALSE

$b
[1] TRUE

$c
[1] TRUE

> l[cond]

Error in l[cond] : invalid subscript type 'list'


This is what the Filter function was made for:

Filter(function(x) length(x) > 3, l)
$b
[1] 4 5 6 5

$c
[1] 3 4 5 6


Another way is to use sapply instead of lapply.

cond <- sapply(l, function(x) length(x) > 3)
l[cond]


[ is expecting a vector, so use unlist on cond:

l[unlist(cond)]
$b
[1] 4 5 6 5

$c
[1] 3 4 5 6


> l[as.logical(cond)]
$b
[1] 4 5 6 5

$c
[1] 3 4 5 6


I recently learned lengths(), which gets the length of each element of a list. This allows us to avoid making another list including logical values as the OP tried.

lengths(l)
#a b c 
#3 4 4 

Using this in a logical condition, we can subset list elements in l.

l[lengths(l) > 3]

$b
[1] 4 5 6 5

$c
[1] 3 4 5 6


Well im am very new to R but as it is a functional language by far the best solution according to the previous answers is something like:

filter <- function (inputList, selector) sapply(inputList, function (element) selector(element))

Assume you have a complex list like yours:

myList <- list(
    a=c(1,2,3), 
    b=c(4,5,6,5), 
    c=c(3,4,5,6))

Then you can filter the elements like:

selection <- myList[filter(myList, function (element) length(element) > 3]

Well of course this also works for list that just contain a value at the first level:

anotherList <- list(1, 2, 3, 4)
selection <- myList[filter(anotherList, function (element) element == 2)]

Or you can put it all together like:

filter <- function (inputList, selector) inputList[sapply(inputList, function (element) selector(element))]


cond <- lapply(l, length) > 3
l[cond]


l <- list(a=c(1,2,3), b=c(4,5,6,5), c=c(3,4,5,6))

l[lengths(l) > 3]

$b
[1] 4 5 6 5

$c
[1] 3 4 5 6

If a condition on value is needed:

cond <- lapply(l, function(i) i > 3)

res <- Map(`[`, l, cond)

res

$a
numeric(0)

$b
[1] 4 5 6 5

$c
[1] 4 5 6

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜