Home > Software engineering >  Find value drops with jumps in R
Find value drops with jumps in R

Time:01-13

I am trying to find some value drops and classify the complete drop as TRUE or FALSE. Here is some example data with visualization:

df <- data.frame(time = c(1:14),
                 value = c(100, 102, 102, 90, 99, 99, 96, 96, 94, 94, 96, 96, 97, 97))
library(ggplot2)
ggplot(df, aes(x = time, y = value))  
  geom_step()  
  geom_point()

Created on 2023-01-12 with reprex v2.0.2

I would like to find the time steps (3,4,5,6) and (8,9,10,11,12) because I am trying to find values which if the difference with next value < 0 and its next difference stays the same or jumps, that should be the drop. Here is a for-loop I tried:

values <- df$value
result <- rep("FALSE", length(values))

for (i in 2:(length(values)-1)) {
  if (values[i] < values[i-1] && (values[i 1] >= values[i])) {
    result[i-1] <- "TRUE"
    result[i] <- "TRUE"
    result[i 1] <- "TRUE"
  } 
}
result
#>  [1] "FALSE" "FALSE" "TRUE"  "TRUE"  "TRUE"  "TRUE"  "TRUE"  "TRUE"  "TRUE" 
#> [10] "TRUE"  "FALSE" "FALSE" "FALSE" "FALSE"

Created on 2023-01-12 with reprex v2.0.2

But the problem with this is that it thinks that at timestamp 7 it is a value drop, but the next value is although the same but after that drops which isn't the clean drop/jump (the U form) I am looking for.

So I was wondering if anyone knows how to find these kind of value drops/jumps in R?

CodePudding user response:

A for loop using an anchor (ilast):

v <- c(100, 102, 102, 90, 99, 99, 96, 96, 94, 94, 96, 96, 97, 97)
d <- diff(v)
out <- vector("list", length(d)%/%2)
io <- 0L
fall <- FALSE
for (i in 1:length(d)) {
  if (d[i] < 0) {
    ilast <- i
    fall <- TRUE
  } else if (d[i] > 0) {
    if (fall) out[[io <- io   1L]] <- ilast:(i   2L)
    ilast <- i
    fall <- FALSE
  }
}
out <- out[1:io]
out
#> [[1]]
#> [1] 3 4 5 6
#> 
#> [[2]]
#> [1]  8  9 10 11 12
  • Related