Search code examples
rmin

How to go along a numeric vector and mark the index of currently minimal value until finding a smaller one?


I want to obtain the indexes of minimal values such as:

v1 <- c(20, 30, 5, 18, 2, 10, 8, 4)

The result is:

1 3 5

Explanation:

Over v1, we start at value 20. Without moving on, we note the minimal value (20) and its index (1). We ignore the adjacent element because it is greater than 20. So 20 still holds the record for smallest. Then we move to 5, which is smaller than 20. Now that 5 is the smallest, we note its index (3). Since 18 isn't smaller than so-far-winner (5), we ignore it and keep going right. Since 2 is the smallest so far, it is the new winner and its position is noted (5). No value smaller than 2 moves right, so that's it. Finally, positions are:

1 # for `20` 
3 # for `5`
5 # for `2`

Clearly, the output should always start with 1, because we never know what comes next.

Another example:

v2 <- c(7, 3, 4, 4, 4, 10, 12, 2, 7, 7, 8)

# output: 
1 2 8

Which.min() seems to be pretty relevant. But I'm not sure how to use it to get the desired result.


Solution

  • You can use:

    which(v1 == cummin(v1))
    
    [1] 1 3 5
    

    If you have duplicated cumulative minimums and don't want the duplicates indexed, you can use:

    which(v1 == cummin(v1) & !duplicated(v1))
    

    Or:

    match(unique(cummin(v1)), v1)