If I have a vector that is showing the change in slope (produced by the sign function) how do I find the data point/points when the slope change from 1 to -1.
Example vector
1 1 1 1 -1 -1 -1 -1 1 1 1 1 -1 -1 -1 -1 1 1 1 1
Or is there a way to somehow just have an output that tells me how many minima are in the vector defined by when a line segment with a negative slope is followed by a line segment with a positive slope (/). In the above example there would be two minima so the example output would be:
minima
2
In a perfect world, I would love to have an output that looks like this
Minima Location
1 8
1 9
2 16
2 17
CodePudding user response:
There is a nice trick for all of these types of problems. You take a copy of the vector and shift it one to the left and then use a vectorised compare and the minima occur wherever the shifted vector is not equal to the original vector.
So for example:
> a = c(1,1,-1,-1,1,-1)
> n = length(a)
> b = a[-1] # Drop the first element
> d = a[-n] # Drop the last element
> b
[1] 1 -1 -1 1 -1
> d
[1] 1 1 -1 -1 1
> minima = which(b!=d)
> minima
[1] 2 4 5
>
CodePudding user response:
I am not really clear on how you define "minima" locations. But the following returns a vector of locations that matches your expected output.
x <- c(1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, 1, 1, 1)
which(c(0, diff(x)) > 0 | c(diff(x), 0) > 0)
[1] 8 9 16 17
Or if you want to return a data.frame
, perhaps something like this
library(dplyr)
x %>%
enframe(name = "Location") %>%
mutate(is_minimum = c(0, diff(value)) > 0 | c(diff(value), 0) > 0) %>%
filter(is_minimum) %>%
mutate(Minima = cumsum(c(0, diff(Location)) != 1)) %>%
select(-c(value, is_minimum))
## A tibble: 4 x 2
# Location Minima
# <int> <int>
#1 8 1
#2 9 1
#3 16 2
#4 17 2
CodePudding user response:
Another way in base R:
w = which(diff(a) > 0)
# [1] 8 16
length(w) #minima
# [1] 2
data.frame(Minima = rep(seq(w), each = 2),
Location = c(rbind(w, w 1)))
# Minima Location
#1 1 8
#2 1 9
#3 2 16
#4 2 17