Find position of closest value to another value given a condition in R

Viewed 157

let's say I have a vector that increases and then decreases like the simple example below. I want to identify the position (index) in the vector that is closest to a value - but with the condition that the following value must be lower (I always want to pick up the closest value on the downslope of the data).

In the example below, I want the answer to be 13 (rather than 6).

I can't think of a solution using which.min() or match.closest() which would reliably work for this.

Any help gratefully received!

# example vector which increases then decreases
vector <- c(1,2,3,4,5,6,7,8,9,9,8,7,6,5,4,3,2,1)

# index 
index <- c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18)

value <- 6.2
2 Answers

Maybe you can use cummax + rev like below

which.min(abs(rev(cummax(rev(vector)))-value))

which gives

[1] 13

Assuming your points always continue to decrease in value after the first decrease, and value is between the point of the first decrease and the last point, you could do this:

closest <- function(value, vec, next_is){
  lead_fun <- function(x) c(tail(x, -1), NA)
  meets_cond <- get(next_is)(lead_fun(vec), vec)
  which.min(abs(vec[meets_cond] - value)) + which.max(meets_cond) - 1
}

closest(6.2, vec = vector, next_is = '<')
# [1] 13

Check which elements in the vector meet your condition, find the index of the closest element in that vector, then add back the number of elements before the first which meets your condition.

Edit: ----------------------------------------

Another version of the function which accepts an arbitrary logical vector which is TRUE for indices meeting a condition:

closest <- function(value, vec, cond_vec){
  which.min(abs(vec[cond_vec] - value)) + which.max(cond_vec) - 1
}

Note that this assumes the values matching your condition are all in one contiguous region (not e.g. the first matches, then the third, then the sixth, etc.)

If your condition is that the point comes after the max value:

closest(6.2, vec = vector, cond_vec = seq_along(vector) > which.max(vector))
# [1] 13
Related