考虑以下脚本,我们将其称为Foo.r

set.seed(1)
x=matrix(rnorm(1000*1000),ncol=1000)
x=data.frame(x)


dummy = sapply(1:1000,function(i) sum(x[i,]) )
#dummy = sapply(1:1000,function(i) sum(x[,i]) )

当第一条dummy行被注释掉时,我们正在对列求和,并且该代码在我的计算机上运行不到一秒钟。
$ time Rscript Foo.r

real    0m0.766s
user    0m0.536s
sys     0m0.080s

当第二行dummy行被注释掉(第一行被注释掉)时,我们正在对行求和,运行时间接近30秒。
$ time Rscript Foo.r

real    0m30.589s
user    0m30.248s
sys     0m0.104s

请注意,我知道标准的求和函数rowSumscolSums,但是我仅将sum作为这种奇怪的不对称性能行为的示例。

最佳答案

这实际上并不是sapply的结果,而是与数据帧的存储方式以及提取行与列的含义有关。数据帧存储为列表,其中列表的每个元素都是一列。

这意味着提取列比提取行要容易。

为了演示这与sapply无关,请考虑使用数据框x:

foo1 <- function(){
+   for (i in 1:1000){
+       tmp <- x[i, ]
+   }
+ }
>
> foo2 <- function(){
+   for (i in 1:1000){
+       tmp <- x[ ,i]
+   }
+ }
> system.time(foo2())
   user  system elapsed
  0.029   0.000   0.031
> system.time(foo1())
   user  system elapsed
 15.986   0.074  15.894

如果您需要按行且快速地执行操作,则数据帧通常是一个错误的选择。要对行进行操作,它必须从每个列表项中提取相应的元素。要对列进行操作,只需要遍历各列即可。

关于r - 为什么 `sapply`在R中的数据帧中处理行比在列中慢得多?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20319318/

10-16 08:42
查看更多