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.
CodePudding user response:
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)
CodePudding user response:
This is the verbose way:
library(purrr)
v1 <- c(20, 30, 5, 18, 2, 10, 8, 4)
v1 %>%
length() %>%
seq() %>%
map_dbl(~ which.min(v1[1: .x])) %>%
unique()
#> [1] 1 3 5
Created on 2021-12-08 by the reprex package (v2.0.1)