在R中使用向量时,diff
函数计算每个值与前一个值之间的差异。来自?diff
:
如果
x
是长度为n
且differences = 1
的向量,则计算结果等于连续差异x[(1+lag):n] - x[1:(n-lag)]
但是,当我测试diff
函数的执行时间与其理论表达式(使用microbenchmark
包中的microbenchmark
函数)时,diff
函数速度较慢。这是我的代码:
library(microbenchmark)
mb.diff1 <- function(n, seed){
set.seed(seed)
vec <- runif(n)
out <- diff(vec)
return(out)
}
mb.diff2 <- function(n, seed){
set.seed(seed)
vec <- runif(n)
out <- vec[2:n]-vec[1:(n-1)]
return(out)
}
times.diff1 <- c()
times.diff2 <- c()
vec.sizes <- c(1e1, 1e2, 1e3, 1e4)
for (n in vec.sizes){
bench <- microbenchmark(
mb.diff1(n,1),
mb.diff2(n,1))
times.median <- aggregate(
bench$time,
by = list(bench$expr),
FUN = median)
times.diff1 <- c(times.diff1, times.median[1,2])
times.diff2 <- c(times.diff2, times.median[2,2])
}
perf.ratio <- times.diff1/times.diff2
names(perf.ratio) <- vec.sizes
print(perf.ratio)
我完成了1e4的vec.sizes,所以你们的执行时间不会太长,但我会让它们持续到1e7。你可以在这里看到结果:
如您所见,diff
函数对于所有矢量大小都较慢。由于在两种情况下执行时间都是矢量大小的线性函数,因此商容趋于减小,因此我们不能说diff
在n增加时表现更好。所以问题出现了:
diff
函数的原因可能比理论表达式慢?x[(1+lag):n] - x[1:(n-lag)]
?我在Linux中使用R 3.1.2。
非常感谢你。
答案 0 :(得分:0)
以下是一些有助于扩展和说明我在评论中提出的观点的代码。
library(microbenchmark)
mb.diff2 <- compiler::cmpfun(function(vec) {
n <- length(vec)
vec[2:n]-vec[1:(n-1L)]
})
times.diff1 <- c()
times.diff2 <- c()
times.diff3 <- c()
vec.sizes <- c(1e1, 1e2, 1e3, 1e4, 1e5)
for (n in vec.sizes) {
set.seed(21)
vec <- runif(n)
bench <- microbenchmark(diff(vec), mb.diff2(vec), diff.default(vec))
times.median <- aggregate(bench$time, by = list(bench$expr), FUN = median)
times.diff1 <- c(times.diff1, times.median[1,2])
times.diff2 <- c(times.diff2, times.median[2,2])
times.diff3 <- c(times.diff3, times.median[3,2])
}
setNames(times.diff1/times.diff2, vec.sizes)
setNames(times.diff1/times.diff3, vec.sizes)
首先,您会注意到我编译了mb.diff2
函数。这是因为diff
和diff.default
是字节编译的。我还将n
的计算放在mb.diff2
内,因为计算向量长度应该是测量函数调用的一部分。
以下是时间的结果以及我的sessionInfo()
:
R> setNames(times.diff1/times.diff2, vec.sizes)
10 100 1000 10000 1e+05
3.5781536 2.3330988 1.2488135 0.9011312 0.9660411
R> setNames(times.diff1/times.diff3, vec.sizes)
10 100 1000 10000 1e+05
1.5945010 1.4609283 1.1021190 1.0034623 0.9987618
R> sessionInfo()
R version 3.3.2 (2016-10-31)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 16.04.1 LTS
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
[3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
[7] LC_PAPER=en_US.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] microbenchmark_1.4-2
loaded via a namespace (and not attached):
[1] Rcpp_0.12.9 digest_0.6.8 MASS_7.3-45 grid_3.3.2
[5] plyr_1.8.4 gtable_0.1.2 magrittr_1.5 scales_0.3.0
[9] ggplot2_1.0.1 stringi_0.4-1 reshape2_1.4.1 proto_0.3-10
[13] tools_3.3.2 stringr_1.0.0 munsell_0.4.2 compiler_3.3.2
[17] colorspace_1.2-6