【问题标题】:set missing values to constant in R, computational speed在 R 中将缺失值设置为常数,计算速度
【发布时间】:2016-10-17 21:33:02
【问题描述】:

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

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

但这相当慢。在 R 中有没有更好的方法来做到这一点?

我愿意使用其他 R 包。

如果讨论的重点是计算速度,而不是“为什么要用零替换 na”,我会更喜欢它。而且,虽然我意识到有人问过类似的问题 (How do I replace NA values with zeros in an R dataframe?),但重点并不是针对具有许多缺失值的大型数据帧的计算速度。

谢谢!

修改后的解决方案: 正如有用的建议,在应用 is.na 之前将 d 更改为矩阵将计算速度提高了一个数量级

【问题讨论】:

  • 此数据框是否具有相同类型的列(即全数字或全字符)?将其存储为矩阵可能会加快速度。
  • 经常转换为data.table 可以提高许多操作的速度,但is.na.data.table 不是其中之一。
  • @ Spacedman,所有数字 - 抱歉应该指定。将编辑。

标签: r performance dataframe na


【解决方案1】:

使用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

【讨论】:

    【解决方案2】:

    我猜所有列都必须是数字,否则将 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.frames,其中一些也更大,因此速度提升具有实际意义。感谢您的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多