Idea
在你的for
循环中,当你从索引i
开始迭代时,你实际上并不需要获取所有出现的高/低命中,只要在first hit(无论是高还是低)出现在j
处,就停止迭代.然后你用i+1
刷新你的起点,重复上面的过程.
换句话说,你的原点方法min(which(...))
是不必要的低效,因为它给出了所有索引信息,并且只取第一个,而如果你终止迭代,只要你找到第一个命中,然后进入下一轮,它可能会快得多.
Code
也许你可以试试下面的for
个循环
L <- length(x)
hit <- vector(length = L)
for (i in 1:L) {
for (j in i:L) {
d <- x[j] - x[i]
if (d >= con) {
hit[i] <- 1
break
}
if (d <= -con) {
break
}
}
}
benchmark
定义候选人如下
f1 <- function() {
hit <- NULL
for (i in 1:length(x)) {
hithi <- min(which(x[i:length(x)] >= x[i] + con))
hithi <- ifelse(is.infinite(hithi), length(x), hithi)
hitlo <- min(which(x[i:length(x)] <= x[i] - con))
hitlo <- ifelse(is.infinite(hitlo), length(x), hitlo)
hit[i] <- ifelse(hithi < hitlo, 1, 0)
}
hit
}
f2 <- function() {
L <- length(x)
hit <- vector(length = L)
for (i in 1:L) {
xi <- x[i]
for (j in i:L) {
d <- x[j] - xi
if (d >= con) {
hit[i] <- 1
break
}
if (d <= -con) {
break
}
}
}
hit
}
我们运行以下基准测试
set.seed(0)
x <- cumsum(rnorm(10000))
con <- 5
microbenchmark(
f1 = f1(),
f2 = f2(),
times = 10L,
unit = "relative",
check = "equivalent"
)
我们看到,
Unit: relative
expr min lq mean median uq max neval
f1 23.86287 24.56557 23.66208 24.22205 23.91301 21.11874 10
f2 1.00000 1.00000 1.00000 1.00000 1.00000 1.00000 10
显示f2
比f1
快23x
如果你想进一步提高速度,你可以在Rcpp
中重写代码.