RFor循环的最佳构造

示例

为了说明有益于循环构建的效果,我们将以四种不同的方式计算每列的平均值:

  1. 使用优化效果不佳的for循环

  2. 使用优化的for循环

  3. 使用*apply一系列功能

  4. 使用colMeans功能

这些选项中的每一个都将在代码中显示;将显示执行每个选项的计算时间的比较;最后将讨论差异。

循环优化欠佳

column_mean_poor <- NULL
for (i in 1:length(mtcars)){
  column_mean_poor[i] <- mean(mtcars[[i]])
}

循环优化

column_mean_optimal <- vector("numeric", length(mtcars))
for (i in seq_along(mtcars)){
  column_mean_optimal <- mean(mtcars[[i]])
}

vapply 功能

column_mean_vapply <- vapply(mtcars, mean, numeric(1))

colMeans 功能

column_mean_colMeans <- colMeans(mtcars)

效率比较

对这四种方法进行基准测试的结果如下所示(代码未显示)

Unit: microseconds
     expr     min       lq     mean   median       uq     max neval  cld
     poor 240.986 262.0820 287.1125 275.8160 307.2485 442.609   100    d
  optimal 220.313 237.4455 258.8426 247.0735 280.9130 362.469   100   c 
   vapply 107.042 109.7320 124.4715 113.4130 132.6695 202.473   100 a   
 colMeans 155.183 161.6955 180.2067 175.0045 194.2605 259.958   100  b

请注意,优化的for循环消除了构造不良的for循环。for循环构造不良,会不断增加输出对象的长度,并且在每次更改长度时,R都会重新评估对象的类别。

优化的for循环通过在开始循环之前声明输出对象的类型及其长度来消除一些开销负担。

但是,在此示例中,使用vapply函数会使计算效率加倍,这主要是因为我们告诉R结果必须是数字的(如果任何结果都不是数字,则将返回错误)。

使用该colMeans功能比使用该功能要慢一些vapply。这种差异可归因于在函数中未执行的某些错误检查,colMeans并且主要归因于as.matrix转换(因为mtcars是data.frame)vapply。