overwhelmed overwhelmed - 2 months ago 7
R Question

How to identify the position of the first occurring local minimum in a vector?

Say I have the following vector:

y
[1] 10
[2] 9
[3] 8
[4] 6
[5] 7
[6] -3
[7] -1


Though the position of the minimum can be get using
which(y==min(y)
as 6. But I want to know how to get the first minimum which is
6
and the position is
4
. After 6 the value increased to 7.
Thanks in advance.

Answer

Try:

first.min <- function(y) {
  d <- which(diff(y) > 0)
  if (length(d) > 0) d[1] else length(y)
}
first.min(y)
##[1] 4

This gives you the position. To get the minimum value:

y[first.min(y)]
##[1] 6

Update version that accounts for first minimum over multiple elements

Suppose you have the case:

y <- c(10,9,6,6,7,-3,-1)

and you want to find the position of the first 6 as the position of the first minimum. Then, the above function needs to be modified to:

first.min <- function(y) {
  d <- diff(y)
  p <- which(d > 0)
  if (length(p) > 0) p <- p[1] else p <- length(y)
  n <- which(d[1:p[1]] < 0)
  if (length(n) > 0) n[length(n)]+1 else 1
}

Here, we detect the first position of the positive difference as before, but we backtrack to check the position of the last negative difference and return that position plus one. Of course, in this case if we still do want the position of the second 6, then we still need the previous version.

To check:

## As before
y <- c(10,9,8,6,7,-3,-1)
first.min(y)
##[1] 4
y[first.min(y)]
##[1] 6

## New case
y <- c(10,9,6,6,7,-3,-1)
first.min(y)
##[1] 3
y[first.min(y)]
##[1] 6

## 6 is not a minimum, but -3 is
y <- c(10,9,8,6,6,-3,-1)
first.min(y)
##[1] 6
y[first.min(y)]
##[1] -3

## Edge case where minimum is at end
y <- c(10,9,8,6,5)
first.min(y)
##[1] 5
y[first.min(y)]
##[1] 5

## Edge case where minimum is at last 2 elements, but we want
## the first of these
y <- c(10,9,8,6,6)
first.min(y)
##[1] 4
y[first.min(y)]
##[1] 6
Comments