Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 503
Cauchy Avatar asked Apr 28 '15 21:04

Cauchy


People also ask

What is the return type of Sapply ()?

sapply() function takes list, vector or data frame as input and gives output in vector or matrix. It is useful for operations on list objects and returns a list object of same length of original set. Sapply function in R does the same job as lapply() function but returns a vector.

What is the difference between apply and Sapply?

Difference between the apply() and sapply() Functions: The apply() function takes the data frame and a matrix as the input, whereas the sapply() function takes the data frame, vector, and list as the input. The lapply() function also takes the same input as the sapply() function.

What does apply () do in R?

The apply() function lets us apply a function to the rows or columns of a matrix or data frame. This function takes matrix or data frame as an argument along with function and whether it has to be applied by row or column and returns the result in the form of a vector or array or list of values obtained.

Why does Sapply return a list?

The real reason for this is that sapply doesn't know what your function will return without calling it. In your case the function returns a logical , but since sapply is given an empty list, the function is never called. Therefore, it has to come up with a type and it defaults to list .


2 Answers

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.

like image 84
Ben Bolker Avatar answered Oct 14 '22 21:10

Ben Bolker


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
like image 41
David Arenburg Avatar answered Oct 14 '22 21:10

David Arenburg