Cauchy
Cauchy

Reputation: 1747

apply, sapply and lappy return NULL

I have a matrix:

mat <- matrix(c(0,0,0,0,1,1,1,1,-1,-1,-1,-1), ncol = 4 , nrow = 4)

and I apply the following functions to filter out the columns with only positive entries, but for the columns that have negative entries I get a NULL. How can I suppress the NULLs from the output of lapply, apply and sapply?

> lapply(as.data.frame(mat), function(x) { if( all(x >= 0) ){return(x)} })
$V1
[1] 0 0 0 0

$V2
[1] 1 1 1 1

$V3
NULL

$V4
[1] 0 0 0 0

> sapply(as.data.frame(mat), function(x) { if( all(x >= 0) ){return(x)} })
$V1
[1] 0 0 0 0

$V2
[1] 1 1 1 1

$V3
NULL

$V4
[1] 0 0 0 0


> apply(mat, 2, function(x){if (all(x >= 0)){return(x)}})
[[1]]
[1] 0 0 0 0

[[2]]
[1] 1 1 1 1

[[3]]
NULL

[[4]]
[1] 0 0 0 0

Thanks for any help.

Upvotes: 11

Views: 3239

Answers (2)

Ben Bolker
Ben Bolker

Reputation: 226097

How about

dd <- as.data.frame(mat)
dd[sapply(dd,function(x) all(x>=0))]

?

  • sapply(...) returns a logical vector (in this case TRUE TRUE FALSE TRUE) that states whether the columns have all non-negative values.
  • when used with a data frame (not a matrix), single-bracket indexing with a logical vector treats the data frame as a list (which it is) and creates a list containing just the specified elements.

Or alternatively

dd[apply(mat>=0,2,all)]

In this case we use apply(...,2,...) on the original matrix to generate the logical indexing vector.

or

mat[,apply(mat>=0,2,all)]

In this case since we are indexing a matrix we use [,logical_vector] to select columns.

Upvotes: 8

David Arenburg
David Arenburg

Reputation: 92282

Another option is to Filter your result while Negateing NULLs (if you want to keep it in a list format)

Res <- lapply(as.data.frame(mat), function(x) if(all(x >= 0)) x)
Filter(Negate(is.null), Res)
# $V1
# [1] 0 0 0 0
# 
# $V2
# [1] 1 1 1 1
# 
# $V4
# [1] 0 0 0 0

Upvotes: 8

Related Questions