【问题标题】:Apply function take 100 time longer than a For loop in R应用函数比 R 中的 For 循环长 100 倍
【发布时间】:2017-07-05 06:37:45
【问题描述】:

我在for 循环和apply 函数之间遇到了巨大的时间差。

我有一个数据框 (alldat),其中包含大约 200k 条记录和 73 列我想检查每列中 NA 的百分比是多少,并将结果作为新的 DF 返回以供我检查。我已经通过两种方法完成了:

1) 带有for 循环的函数:

Nacheck = function(a){
    a <- as.data.frame(a)
    vecNA <- rep(NA, dim(a)[2])
    for (i in 1:dim(a)[2]){
        vecNA[i] <- sum(is.na(a[, i]))
        }
    rowss <- rep(nrow(a), length(vecNA))
    NA_PCT <- vecNA/rowss
    colna <- colnames(a)
    datacheck <- as.data.frame(t(rbind(colna, NA_PCT)))
    return(datacheck)
}
datacheck1 = Nacheck(alldat)

2)apply按列函数:

datacheck <- as.data.frame(apply(alldat,2,function (x) round(sum(is.na(x))/dim(alldat)[1], digits = 2)))

apply 函数耗时 4 秒,for 循环函数耗时不到 0.023 秒

start.time <- Sys.time()
datacheck <- as.data.frame(apply(alldat,2,function (x) round(sum(is.na(x))/dim(alldat)[1], digits = 2)))
end.time <- Sys.time()
time.takenapply <- end.time - start.time
time.takenapply

4.304 秒的时差

for 循环时间:

start.time <- Sys.time()
datacheck = Nacheck(alldat)
end.time <- Sys.time()
time.taken <- end.time - start.time
time.taken

0.02399993秒的时间差

我做错了吗?知道是什么导致了这个时差吗?

【问题讨论】:

  • apply 函数将矩阵作为参数。输入数据到矩阵的内部转换可能会导致此时间差。另外我会改用lapply,因为您对列执行计算。
  • apply(df,2,function(x) sum(is.na(x)))
  • 不是这个原因,但为什么不使用nrow(a),ncol(a) 而不是dim(a)[1],dim(a)[2]
  • 请提供一个可重现的例子
  • 或许可以试试colMeans(is.na(alldat))

标签: r for-loop apply


【解决方案1】:

日期框架在内部与列表非常相似,每一列都是列表中的一个单独条目。您可以使用$ 运算符来查看这一点。这允许您指定列,类似于在列表中指定命名条目。

当您执行 apply 时,正如 Natrave Drova 在 cmets 中已经提到的那样,您正在隐式地将整个数据帧转换为矩阵。如果您的数据框随后具有不同的数据类型,例如数字列和字符列,它会将所有值强制转换为通用类型(通常是字符)。如果您的数据框很大(并且要强制转换的 200k * 73 个值也算大),这可能是一项非常昂贵的操作。

因此,如果您想正确比较 *apply 函数和 for 循环,您应该尝试使用 lapply 代替。

【讨论】:

    猜你喜欢
    • 2017-11-29
    • 1970-01-01
    • 1970-01-01
    • 2020-11-07
    • 2013-06-19
    • 1970-01-01
    • 2022-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多