Stack Overflow for Teams is a private, secure spot for you and
your coworkers to find and share information.
Learn more
I am working on
NDVI Time-Series
Data which has
23 observations
in a year. I am able to detect the peaks occurring between the
14 - 19 observation
. Now I want to find the
start and end of the Peak
. I am able to find the start and end of peak by looking for sign change using
diff function
. But in some cases I am note able to find the end, as end of the peak is in next year. Solution is to repeat the values after 23 observation to make it cyclic and find the end.
Example given below will explain the problem in detail
x = c(250.7943,292.2904,340.459,368.811,363.4534,330.2302,291.6527,275.2815,299.9305,367.0331,461.2618,559.0772,639.6197,691.723,713.9833,709.5409,680.4415,626.1153,547.0395,450.4623,353.0839,277.257,241.597)
I am looking for sign change from the Peak in both direction and able to find the start of the peak at 8 observation but when I am looking for the end starting from Peak I am not able to find any change till 23. In this case I should get the end the peak at 23. As shown in table I have repeated the values manually in Excel to get the Sign change.
How this can be done in R???
One solution may be that putting a condition to check if sign change is not found till 23 observation then all 23 values will be padded at end of the vector and then look for the sign change.
Is there a simple approach to accomplish this???
Another possibility:
(1) Pad your values with leading and lagging Inf to create dummy local minima* in the start and end of the time series. (2) Find indexes of all minima (including the dummies). (3) Find indexes of the two minima which are next to the maximum.
# pad values with Inf and get indexes of all local minima
i.mins <- which(diff(sign(diff(c(Inf, x, Inf)))) == 2)
# index of max value
i.mx <- which.max(x)
# combine indexes of local minima and the max
i <- sort(c(i.mins, i.mx))
# select the two minima on either side of the max
ix <- i[which(i == i.mx) + c(-1, 1)]
# [1] 8 23
–
–
This is just to create a reproducible example:
y = data.frame(x = x, y = c(x[2:length(x)], NA))
y$diff <- y$y - y$x
Then we start by generating a new column:
y$startEndPeak <- NA
Afterwards we loop over the data.frame holding all difference records. Thus we identify start/end points and peaks by comparing all differences with their previous conterpart:
for(i in 2:(nrow(y) - 1)){
thisDif <- y$diff[i]
prevDif <- y$diff[i-1]
if (thisDif < 0 && prevDif > 0){
y$startEndPeak[i] <- "start/end"
if (thisDif > 0 && prevDif < 0){
y$startEndPeak[i] <- "peak"
# x y diff startEndPeak
# 1 250.7943 292.2904 41.4961 <NA>
# 2 292.2904 340.4590 48.1686 <NA>
# 3 340.4590 368.8110 28.3520 <NA>
# 4 368.8110 363.4534 -5.3576 start/end
# 5 363.4534 330.2302 -33.2232 <NA>
# 6 330.2302 291.6527 -38.5775 <NA>
# 7 291.6527 275.2815 -16.3712 <NA>
# 8 275.2815 299.9305 24.6490 peak
# 9 299.9305 367.0331 67.1026 <NA>
# 10 367.0331 461.2618 94.2287 <NA>
# 11 461.2618 559.0772 97.8154 <NA>
# 12 559.0772 639.6197 80.5425 <NA>
# 13 639.6197 691.7230 52.1033 <NA>
# 14 691.7230 713.9833 22.2603 <NA>
# 15 713.9833 709.5409 -4.4424 start/end
# 16 709.5409 680.4415 -29.0994 <NA>
# 17 680.4415 626.1153 -54.3262 <NA>
# 18 626.1153 547.0395 -79.0758 <NA>
# 19 547.0395 450.4623 -96.5772 <NA>
# 20 450.4623 353.0839 -97.3784 <NA>
# 21 353.0839 277.2570 -75.8269 <NA>
# 22 277.2570 241.5970 -35.6600 <NA>
# 23 241.5970 NA NA <NA>
then we use vectors to place start and end points
y$startEndPeak[which(y$startEndPeak == "start/end")] <- c("start", "end")
# x y diff startEndPeak
# ...........
# 3 340.4590 368.8110 28.3520 <NA>
# 4 368.8110 363.4534 -5.3576 start
# ...........
# 8 275.2815 299.9305 24.6490 peak
# ...........
# 15 713.9833 709.5409 -4.4424 end
# ...........
–
Usimg Loki's Approach I am able to partially solve my problem....
y = data.frame(x = x, y = c(x[2:length(x)], x[1]))
y$diff <- y$y - y$x
y$startEndPeak <- NA
for(i in 2:(nrow(y))){
thisDif <- y$diff[i]
prevDif <- y$diff[i-1]
if (thisDif < 0 && prevDif > 0){
y$startEndPeak[i] <- "peak"
if (thisDif > 0 && prevDif < 0){
y$startEndPeak[i-1] <- "end"
y$startEndPeak[i] <- "start"
# x y diff startEndPeak
# 250.7943 292.2904 41.4961 <NA>
# 292.2904 340.4590 48.1686 <NA>
# 340.4590 368.8110 28.3520 <NA>
# 368.8110 363.4534 -5.3576 peak
# 363.4534 330.2302 -33.2232 <NA>
# 330.2302 291.6527 -38.5775 <NA>
# 291.6527 275.2815 -16.3712 end
# 275.2815 299.9305 24.6490 start
# 299.9305 367.0331 67.1026 <NA>
# 367.0331 461.2618 94.2287 <NA>
# 461.2618 559.0772 97.8154 <NA>
# 559.0772 639.6197 80.5425 <NA>
# 639.6197 691.7230 52.1033 <NA>
# 691.7230 713.9833 22.2603 <NA>
# 713.9833 709.5409 -4.4424 peak
# 709.5409 680.4415 -29.0994 <NA>
# 680.4415 626.1153 -54.3262 <NA>
# 626.1153 547.0395 -79.0758 <NA>
# 547.0395 450.4623 -96.5772 <NA>
# 450.4623 353.0839 -97.3784 <NA>
# 353.0839 277.2570 -75.8269 <NA>
# 277.2570 241.5970 -35.6600 end
# 241.5970 250.7943 9.1973 start
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.