应用函数比R中的For循环长100倍

时间:2017-07-05 06:37:46

标签: r for-loop apply

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

我有一个数据帧(alldat),包含大约200k条记录和73列我想检查每列中NA的百分比,并将结果作为新DF返回给我进行检查。我用2种方法完成了它:

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秒

我做错了吗?知道造成这种时差的原因吗?

1 个答案:

答案 0 :(得分:1)

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

当您apply时,正如Natrave Drova在评论中已经提到的那样,您隐式将您的entiry数据帧转换为矩阵。如果您的数据帧具有不同的数据类型,例如数字列和字符列,则它会将所有值强制转换为公共类型(通常是字符)。如果你的数据帧很大(并且200k * 73的值是强制的那么大),这可能是一个非常昂贵的操作。

因此,如果您想要正确地将*apply函数与for循环进行比较,则应该使用lapply进行尝试。