在 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
在 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