-1

这是带有输出的示例代码:

set.seed(234)
a <- matrix(rnorm(100000), 10000,100)
dim(a)

fo1 <- function() apply(a, 1, sum)
fo2 <- function() a %*% rep(1, 100)
fo3 <- function() {
    n <- nrow(a)
    x <- numeric(n)
    for(i in seq_len(n))  x[i] <- sum(a[i, ])
    }
fo4 <- function() rowSums(a)

# install.packages("microbenchmark")
require(microbenchmark)

microbenchmark(fo1 , fo2, fo3, fo4 ,times = 100000)
# expr min lq median uq    max neval
#  fo1  81 90     91 96 188969 1e+05
#  fo2  75 87     90 94 241332 1e+05
#  fo3  75 84     87 91 271085 1e+05
#  fo4  72 88     91 97 39447 1e+05

我认为 apply 和 loops 应该比矢量化版本或专用 rowSums 函数慢 - 但它们似乎都给出了非常相似的结果(最大值除外)。

任何人都可以提出为什么会这样吗?

4

1 回答 1

3

就像@Martin 指出的那样,您没有调用 microbenchmark 中的函数。此外,该函数fo3不返回任何内容:

fo3 <- function() {
    n <- nrow(a)
    x <- numeric(n)
    for(i in seq_len(n))  x[i] <- sum(a[i, ])
    x #you missed this
}

fo2返回矩阵,而其他函数返回向量。所以让我们使用

fo2 <- function() c(a %*% rep(1, 100))

以下是正确的结果:

microbenchmark(fo1() , fo2(), fo3(), fo4() ,times = 100)
Unit: milliseconds
  expr       min        lq    median        uq       max neval
 fo1() 33.437565 37.859724 39.961079 41.409828 85.950181   100
 fo2()  1.756187  1.820632  1.861232  1.899416  2.138938   100
 fo3() 35.356449 37.069169 37.713325 39.624361 51.001235   100
 fo4()  2.467656  2.529235  2.561986  2.616621  2.884215   100

您会看到矩阵向量乘法是最快的,尽管差异rowSums非常小(调用内部.rowSums而不影响结果)。apply和循环方法之间的差异for也很小,就像apply变相的循环一样。

注意

> identical(fo1(),fo2())
[1] FALSE
> identical(fo1(),fo3())
[1] TRUE
> identical(fo1(),fo4())
[1] TRUE
> all.equal(fo1(),fo2())
[1] TRUE

矩阵乘法版本给出的结果与其他版本略有不同。

于 2013-03-19T11:37:50.747 回答