Subset elements in a list based on a logical condition

Viewed 55215

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] 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'

8 Answers

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

Related