对于向量中的每个元素,找到其前后最小

时间:2017-03-22 16:32:17

标签: r

考虑以下向量:

Y <- c(2, 3, 2, 3, 4, 3, 1, 7, 2)

我需要创建一个循环,它找到向量中最大的元素,其前后元素之间的间隔(不包括)的长度值较小,如果这两个元素之间的元素至少与当前检查的元素本身的值。如果元素的前面或后面没有值较小的元素,我们会计算该边的所有元素。在我的示例中,我使用变量Z来跟踪我们在向量中导航时找到的最大值。

# we start with Z <- 0
    .
[1] 2 3 2 3 4 3 1 7 2
                ^

我们向量中的第一个值是2。没有前面的数字,较小的后续数字是标记为1。标记的1和向量的开头之间的间隔(不包括)大于我们现在正在检查的元素(2),因此我们将此元素的值设置为ZZ <- 2

# Z is now 2 from examining previous element
      .
[1] 2 3 2 3 4 3 1 7 2
    ^   ^

下一个元素是3,我们搜索小于3的前后元素。它们标记在上面,因为它们之间只有一个元素,所以我们对这个元素不再感兴趣。 2之间应该至少有三个元素,因为我们目前正在检查值3的元素。没有对Z进行任何更改。

# Z is still 2
        .
[1] 2 3 2 3 4 3 1 7 2
                ^

如果我们优化代码,我们可以直接跳过此2Z已经2,因此该元素无法将其更改为更大的值,因此我们并不真正有兴趣在这里继续进行。如果由于某种原因我们不想跳过这个,则没有先前的较小元素,并且标记1是以下较小的元素。它们的间隔为6,大于我们当前正在检查的元素2。如果Z尚未匹配此元素,我们将设置Z以匹配此元素。它是,所以没有变化。

# Z is still 2
          .
[1] 2 3 2 3 4 3 1 7 2
        ^       ^

下一个元素是3,前面和后面的数字标记在上面。他们的间隔(不包括)是3,它至少是我们当前正在检查的元素的值,因此我们更新Z <- 3

# Z is now 3
            .
[1] 2 3 2 3 4 3 1 7 2
          ^   ^

下一个元素是4。上面标出了较小的前面和后面的元素。由于它们的间隔(不包括)小于4个元素,因此我们对此元素不感兴趣。

# Z is still 3
              .
[1] 2 3 2 3 4 3 1 7 2
        ^       ^

下一个元素是3。我们可以再次跳过此内容,因为此元素无法更改Z的值,因为Z已经3

# Z is still 3
                .
[1] 2 3 2 3 4 3 1 7 2

下一个元素是1。我们可以再次跳过此内容,因为此元素无法更改Z的值,因为Z已经3

# Z is still 3
                  .
[1] 2 3 2 3 4 3 1 7 2
                ^   ^

下一个元素是7。紧接在元素之前和之后的元素比它小,所以我们对这个元素不再感兴趣。两个元素之间至少应有7个元素,其值小于当前元素。

# Z is still 3
                    .
[1] 2 3 2 3 4 3 1 7 2
                ^

下一个元素是2。我们可以再次跳过此内容,因为此元素无法更改Z的值,因为Z已经3

我们现在已经浏览了整个向量,并且我们已经找到了最大元素,其中前一个和后一个最小值之间的间隔(不包括)的长度至少与元素本身一样多。

现在,我有一个包含数十万个数字的数据集,范围从1到数千。

3 个答案:

答案 0 :(得分:0)

这可能是一个开始:

dummy <- data.frame()

for (i in 1:length(y)) {

  b <- ifelse(min(y[1:i-1]) < y[i], i - max(which(y[1:i-1] == min(y[1:i-1]), T)), i)
  a <- ifelse(min(y[(i+1):length(y)]) < y[i], min(which(y[(i+1):length(y)] == min(y[(i+1):length(y)]), T)), length(y) - i)

  ln <- c(y[i], b,  a)

  dummy <- rbind(dummy, ln)

}

弹出一个df,其中包含三个字段 - 原始向量,每个元素之间的空格数和最接近的前一个小于当前值的最小值,以及当前值与最近值之间的空格数以下最小值小于当前值。

在编辑之前写了这个,我不太清楚你的Z应该如何运作。

答案 1 :(得分:0)

Given the text that you have provided:

      .
2 3 2 3 4 3 1 7 2

The following code will do the trick in linear time, though I'm operating under the assumption that another vector is present to indicate the index of the target integer (perhaps you used readLines()):

dot <- c(' ', ' ', ' ','.',' ', ' ', ' ', ' ', ' ')
Y <- c(2, 3, 2, 3, 4, 3, 1, 7, 2)

myBestGuess <- function(dot, y){
    tmp <- which(dot == '.')
    i <- tmp+1
    res <- 0
    while(i <= length(y)){
        if (y[i] <= y[tmp]){
            res <- res + 1
            i <- i + 1
        } else {
            break
        }
    }
    i <- tmp-1
    while(i > 0){
        if (y[i] <= y[tmp]){
            res <- res + 1
            i <- i - 1
        } else {
            break
        }
    }
    return(res)
}

print(myBestGuess(dot, Y))

The output:

[1] 3

答案 2 :(得分:0)

我会把这个操作分成三部分。首先,你可以计算出在你找到一个小于当前位置元素的元素之前你要走多远的距离(假设整个向量的左边有一个负无穷大,所以例如第一个元素去在找到较小值之前的左边一个位置):

(left.dist <- sapply(seq_along(Y), function(i) 1+i-max(which(c(-Inf, head(Y, i-1)) < Y[i]))))
# [1] 1 1 3 1 1 3 7 1 2

同样地,在你发现一个小于当前位置元素的元素之前,我会计算你必须走多远的距离:

(right.dist <- sapply(seq_along(Y), function(i) min(which(c(tail(Y, -i), -Inf) < Y[i]))))
# [1] 6 1 4 3 1 1 3 1 1

每个位置周围感兴趣范围内的元素数量为left.dist + right.dist - 1,因此在向量中找到至少其值的最大值是向量索引中的一个简单练习:

max(Y[left.dist + right.dist - 1 >= Y])
# [1] 3