用该列的中位数替换矩阵每一列中的 NA

Posted

技术标签:

【中文标题】用该列的中位数替换矩阵每一列中的 NA【英文标题】:Replacing NA's in each column of matrix with the median of that column 【发布时间】:2016-04-24 06:38:52 【问题描述】:

我试图,但是当我尝试使用 lapplysapply 时出现错误;当我使用 for 循环并且一次更改一列时,代码有效,我做错了什么?

例子:

set.seed(1928)
mat <- matrix(rnorm(100*110), ncol = 110)
mat[sample(1:length(mat), 700, replace = FALSE)] <- NA
mat1 <- mat2 <- mat

mat1 <- lapply(mat1,
  function(n) 
     mat1[is.na(mat1[,n]),n] <- median(mat1[,n], na.rm = TRUE)
  
)   

for (n in 1:ncol(mat2)) 
  mat2[is.na(mat2[,n]),n] <- median(mat2[,n], na.rm = TRUE)

【问题讨论】:

matrix 对象是有维度的向量。 lapply 将循环遍历矩阵中的每个值而不是列。 如果您感觉超级懒惰并且不想编写自己的函数,您可以使用randomForest 库中的na.roughfix。它会根据是否为数字/因子自动将所有 NA 值替换为中值/众数。 @Jonno Bourne,如果您询问的是数据框而不是矩阵,请编辑您的可重现示例以提供数据框。请注意,这会使已接受的解决方案无效... @smci 这个问题没有提到数据框,并且已经成功回答,一年半前使用矩阵,您能否澄清您的评论。 @JonnoBourne:我知道已经回答了,这就是我的意思,这个措辞含糊的问题是 being (wrongly) cited as a canonical answer elsewhere on SO 用于替换数据帧中的 NA。模糊的标题并没有明确说明它不适用于数据框,因此需要编辑标题。 (事实证明,“用列中位数替换数据帧中的 NA”没有规范的答案。因此,我们需要防止关于该主题的问题错误地被关闭为重复。好吗? 【参考方案1】:

lapply 循环遍历一个列表。你的意思是遍历列吗?

matx <- sapply(seq_len(ncol(mat1)), function(n) 
  mat1[is.na(mat1[,n]),n] <- median(mat1[,n], na.rm = TRUE)
)

虽然这基本上只是在做你的循环示例所做的事情(但可能更快)。

【讨论】:

【参考方案2】:

您可以通过转换为data.frame 并返回matrix 来更轻松地到达那里,结果使用vapply

vapply(as.data.frame(mat1), function(x)
   replace(x, is.na(x), median(x,na.rm=TRUE)), FUN.VALUE=numeric(nrow(mat1)) 
)

【讨论】:

【参考方案3】:

我建议使用matrixStats 包对其进行矢量化,而不是使用任一循环计算每列的中位数(sapply 在某种意义上也是一个循环,它在每次迭代中评估一个函数)。

首先,我们将创建一个NAs 索引

indx <- which(is.na(mat), arr.ind = TRUE)

然后,使用预先计算的列中位数并根据索引替换NAs

mat[indx] <- matrixStats::colMedians(mat, na.rm = TRUE)[indx[, 2]]

【讨论】:

我实际上意识到我想在数据帧上做,但我可以转换为矩阵并执行此操作然后再转换回来,谢谢。 在大多数情况下,您有一个数字数据集,使用矩阵比data.frame 更有效。即使您使用简单的循环。【参考方案4】:

你可以使用sweep:

sweep(mat, MARGIN = 2, 
      STATS = apply(mat, 2, median, na.rm=TRUE),
      FUN =  function(x,s) ifelse(is.na(x), s, x)
    )

编辑: 您也可以加入 STATS=matrixStats::colMedians(mat, na.rm=TRUE) 以获得更多性能。

【讨论】:

以上是关于用该列的中位数替换矩阵每一列中的 NA的主要内容,如果未能解决你的问题,请参考以下文章

为分类算法准备数据

如何用同一数据框中其他列的实际列值替换一列中的字符串值?

将列中的 NA 替换为相邻列中的值

R中是不是有一种方法,如果一列的值满足另一列中的某个标准,则该列的值应该是上面的值

为啥在数据帧上具有中位数的 fillna 仍然在熊猫中留下 Na/NaN?

MATLAB中如何构造一个矩阵,该矩阵中每一列个数不等