4

我正在尝试用该列的中位数替换矩阵每一列中的 NA,但是当我尝试使用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)
}
4

4 回答 4

7

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

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

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

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

mat[indx] <- matrixStats::colMedians(mat, na.rm = TRUE)[indx[, 2]]
于 2016-01-18T23:39:10.227 回答
2

您可以使用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)以获得更多性能。

于 2016-01-19T00:24:43.690 回答
1

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

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

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

于 2016-01-18T23:19:37.027 回答
0

因此,您可以通过转换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)) 
)
于 2016-01-18T23:28:11.930 回答