R中lapply处理含NULL的矩阵列表执行col_norm列归一化报错解决方案
问题背景
我有一个存储不同尺寸矩阵的列表,结构如下:
> MDP$B [,1] [,2] [,3] [,4] [1,] numeric,4 NULL NULL NULL [2,] numeric,16 numeric,16 numeric,16 numeric,16
如下代码处理无NULL值的同结构列表时均可正常运行,单独对上述列表的[[1,1]]等单个元素执行也正常,经排查问题来自列表中的NULL值,运行时报错x must be numeric:
if(isfield(MDP,"b")){ MDP$b = lapply(MDP$b,col_norm) } else{ MDP$b = lapply(MDP$B,col_norm) }
其中col_norm是用于列向量归一化的函数,定义如下:
col_norm = function(x){t(t(x)/colSums(x))}
我现在有两个需求:
- 有没有办法让
lapply直接跳过NULL值执行? - 是否可以完全删除[1,2]、[1,3]、[1,4]位置的NULL元素,从根源避免该问题?
注:此前代码笔误将
isfield(MDP, "b")写为"b1",已修正。
解决方案
方案1:lapply执行时跳过NULL(保留原列表结构)
可使用匿名函数对元素判空,非NULL才执行col_norm,写法如下:
MDP$B = lapply(MDP$B,function(x) if (!is.null(x)) col_norm(x) else NULL)
执行上述代码后需运行dim(MDP$B) = matrix(c(2,4))重设列表维度。
也可以采用如下写法避免重设维度操作:
MDP$b[] <- lapply(MDP$b, \(x) if (!is.null(x)) col_norm(x) else NULL)
方案2:彻底删除NULL元素
如果不需要保留原有的2行4列二维列表结构,可以直接用Filter过滤所有NULL值:
# 过滤后返回一维列表,仅包含非NULL的矩阵元素 MDP$B <- Filter(Negate(is.null), MDP$B)
如果需要保留二维结构仅删除指定位置的NULL,也可以直接裁剪对应行列:
# 删除第一行的第2到4列,保留2行1列的二维结构 MDP$B <- MDP$B[, -c(2:4)]
内容的提问来源于stack exchange,提问作者Steffen Schwerdtfeger
相关产品推荐
相关产品推荐

