我有一个向量x,并且想知道向量(x[i])中的每个元素i的后续数字序列是先到达x[i] + con还是先到达x[i] - con(其中con是常数).当第一次击中x[i] + con时,我希望得到1,否则得到0.

我会用R做这个,如下面最小的工作示例所示:

x   <- cumsum(rnorm(1000000))
con <- 10

hit <- NULL
for (i in 999000:length(x)) {
  hithi  <- min(which(x[i:length(x)] >= x[i] + con))
  hithi  <- ifelse(is.infinite(hithi), 1000000, hithi)
  hitlo  <- min(which(x[i:length(x)] <= x[i] - con))
  hitlo  <- ifelse(is.infinite(hitlo), 1000000, hitlo)
  hit[i] <- ifelse(hithi < hitlo, 1, 0)
  if (i %% 1000 == 0) {
    print(i)
  }
}

然而,你会发现这是非常慢的,因此我想知道是否有更快的方法来获得结果.你会怎么做?

提前感谢!

推荐答案

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

显示f2f123x如果你想进一步提高速度,你可以在Rcpp中重写代码.

R相关问答推荐

如何在ggplot 2 geom_segment图表中将UTC转换为EET?

使用ggcorrplot在相关性矩阵上标注supertitle和index标签

geom_Ribbon条件填充创建与数据不匹配的形状(ggplot 2 r)

使用gggrassure减少地块之间的空间

R spatstat Minkowski Sum()返回多个边界

`夹心::vcovCL`不等于`AER::tobit`标准错误

'使用`purrr::pwalk`从嵌套的嵌套框架中的列表列保存ggplots时出现未使用的参数错误

优化从每个面的栅格中提取值

防止在更新SHINY中的Reactive Value的部分内容时触发依赖事件

用多边形替换地块点

使用ifElse语句在ggploy中设置aes y值

Ggplot2如何找到存储在对象中的残差和拟合值?

R-使用stri_trans_General()将其音译为德语字母

根据排名的顶点属性调整曲线图布局(&Q)

策略表单连接两个非常大的箭头数据集,而不会 destruct 内存使用

R dplyr::带有名称注入(LHS of:=)的函数,稍后在:=的RHS上引用

图中显示错误 colored颜色 的图例geom_sf

修复标签重叠和ggploy内的空间

对数据帧中的列进行子集设置以通过迭代创建新的数据帧

在子图内和子图之间对齐行数不均匀的表格罗布对