以下是带输出的示例代码:
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和循环应该比矢量化版本或专用的rowSums函数慢 - 但它们似乎都给出了非常相似的结果(除了最大值)。
有人能说明为何会出现这种情况吗?
答案 0 :(得分: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
矩阵乘法版本的结果与其他版本略有不同。