I have a list with matrices of different sizes that looks like this:
> MDP$B
[,1] [,2] [,3] [,4]
[1,] numeric,4 NULL NULL NULL
[2,] numeric,16 numeric,16 numeric,16 numeric,16
The following works with previous lists and also works, if I only apply it to e.g. [[1,1]] in the upper list, so the NULL values are the problem.
if(isfield(MDP,"b")){
MDP$b = lapply(MDP$b,col_norm)
} else{
MDP$b = lapply(MDP$B,col_norm)
}
The function col_norm looks like this and normalizes colum vectors:
col_norm = function(x){t(t(x)/colSums(x))}
I get the error x must be numeric. Is there a way to make lapply just skip the NULL values? OR is it possible to fully delete [1,2],[1,3] and [1,4], so that the problem can`t occur?
NOTE: it was supposeds to say isfield(MDP, "b") not "b1", sorry for confusion.
SOLUTION BY @Roland: You can always use an anonymous function function(x) if (!is.null(x)) col_norm(x) else NULL. – Roland
Final line looks like this:
MDP$B = lapply(MDP$B,function(x) if (!is.null(x)) col_norm(x) else NULL)
I had to redim the list with "dim(MDP$B) = matrix(c(2,4))", but thats fine :))
dim(MDP$B) = matrix(c(2,4))
SOLUTION TO THAT also by @Roland: use: MDP$b[] <- lapply(MDP$b, (x) if (!is.null(x)) col_norm(x) else NULL)
CodePudding user response:
In colSums
function there is a na.rm
parameter:
col_norm = function(x){t(t(x)/colSums(x, na.rm=TRUE))}
Or if they are NULL
, also do:
col_norm = function(x){t(t(x)/colSums(replace(x, NULL, NA), na.rm=TRUE))}
CodePudding user response:
Create an anonymous function that checks if it is passed NULL
. You also may want to use [<-
instead of =
to assign into the matrix and preserve its class and dimensions. Both together:
MDP$b[] <- lapply(MDP$b, \(x) if (!is.null(x)) col_norm(x) else NULL)