考虑以下脚本,我们将其称为 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
请注意,我知道标准求和函数
rowSums
和 colSums
,但我仅将 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/