在 R 中将缺失值设置为常量,计算速度

set missing values to constant in R, computational speed

在 R 中,我有一个相当大的数据框 (d),它是 10500 x 6000。所有值都是数字。 它的行和列中都有许多 na 值元素,我希望用零替换这些值。我用过:

d[is.na(d)] <- 0

但这相当慢。在 R 中有更好的方法吗?

我愿意使用其他 R 包。

如果讨论的重点是计算速度而不是 "why would you replace na's with zeros",我会更喜欢它。而且,虽然我意识到有人问过类似的问题 (How do I replace NA values with zeros in an R dataframe?),但重点并未放在具有许多缺失值的大型数据帧上的计算速度上。

谢谢!

已编辑解决方案: 正如建议的那样,在应用 is.na 之前将 d 更改为矩阵可将计算速度提高一个数量级

我想所有列都必须是数字,否则将 0 分配给 NA 是不明智的。

我得到以下计时,大约有 10,000 个 NA:

> M <- matrix(0, 10500, 6000)
> set.seed(54321)
> r <- sample(1:10500, 10000, replace=TRUE)
> c <- sample(1:6000, 10000, replace=TRUE)
> M[cbind(r, c)] <- NA
> D <- data.frame(M)
> sum(is.na(M)) # check
[1] 9999
> sum(is.na(D)) # check
[1] 9999
> system.time(M[is.na(M)] <- 0)
   user  system elapsed 
   0.19    0.12    0.31 
> system.time(D[is.na(D)] <- 0)
   user  system elapsed 
   3.87    0.06    3.95 

因此,有了这个数量的 NA,我通过使用矩阵获得了大约一个数量级的加速。 (NA 越少,差异越小。)但是在我的笔记本电脑上使用数据帧的时间仅为 4 秒——比回答问题所花的时间少得多。如果问题确实如此严重,为什么这么慢?

希望对您有所帮助。

使用 data.table 包可以显着提高性能。 一般来说,它的速度要快得多,有很多操作和转换。 缺点是语法的学习曲线。 但是,如果您正在寻求速度性能提升,那么投资可能是值得的。

生成假数据

r <- 10500  
c <- 6000
x <- sample(c(NA, 1:5), r * c, replace = TRUE)
df <- data.frame(matrix(x, nrow = r, ncol = c))

基础 R

df1 <- df
system.time(df1[is.na(df1)] <- 0)

   user  system elapsed 
   4.74    0.00    4.78 

tidyr - replace_na()

dfReplaceNA <- function (df) {
  require(tidyr)
  l <- setNames(lapply(vector("list", ncol(df)), function(x) x <- 0), names(df))
  replace_na(df, l)
}
system.time(df2 <- dfReplaceNA(df))

   user  system elapsed 
   4.27    0.00    4.28 

data.table - set()

dtReplaceNA <- function (df) {
  require(data.table)
  dt <- data.table(df)
  for (j in 1:ncol(dt)) {set(dt, which(is.na(dt[[j]])), j, 0)}
  setDF(dt)  # Return back a data.frame object
}
system.time(df3 <- dtReplaceNA(df))

   user  system elapsed 
   0.80    0.31    1.11 

比较数据帧

all.equal(df1, df2)

[1] TRUE

all.equal(df1, df3)

[1] TRUE