Home > Enterprise >  Calculating the Number of Observations Since an Event Occurred
Calculating the Number of Observations Since an Event Occurred

Time:05-19

I have the following vector of temperatures (in ˚ C):

Temperature <- c(-3:3, 3:-3, rep(-3, 2), -2:-1, 1:3, 2:1, -1:-4)

I need to calculate the time (number of observations) elapsed since the last freeze event and I also need to calculate the number of observations elapsed since the last thaw event. Freeze events are marked by temperature transitions from positive to negative values, and thaw events are marked by temperature transitions from negative to positive values. The output should look like these vectors:

Time_Since_Last_Freeze <- c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 1, 2, 3)
Time_Since_Last_Thaw <- c(NA, NA, NA, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 1, 2, 3, 4, 5, 6, 7, 8)

I've seen a few similar questions on Stack Overflow but none of them are exactly what I need. What are some efficient ways to generate these two output vectors?

CodePudding user response:

You can use this function, which basically checks the index of freeze and thaw in the original vector, then compute apply a sequence of consecutive number of length dif between every freeze or thaw moments:

f <- function(temp, freeze){
  if(freeze)
    idx <- which(temp <= 0 & dplyr::lag(temp) > 0)
  else
    idx <- which(temp >= 0 & dplyr::lag(temp) < 0)
  
  diff <- diff(c(idx, length(temp)   1))
  vec <- rep(NA, length(temp))
  vec[min(idx):length(temp)] <- unlist(sapply(diff, \(x) seq_len(x) - 1))
  vec
}

output

f(Temperature, freeze = TRUE)
[1] NA NA NA NA NA NA NA NA NA NA  0  1  2  3  4  5  6  7  8  9 10 11 12  0  1  2  3

f(Temperature, freeze = FALSE)
[1] NA NA NA  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14  0  1  2  3  4  5  6  7  8

CodePudding user response:

Not your desired output, though something you might find useful in cgwtools:

temp <- c(-3:3, 3:-3, rep(-3, 2), -2:3, 2:-4)
which(temp > 0)
 [1]  5  6  7  8  9 10 20 21 22 23 24
cgwtools::seqle(which(temp > 0))
Run Length Encoding
  lengths: int [1:2] 6 5
  values : int [1:2] 5 20
> cgwtools::seqle(which(temp <= 0))
Run Length Encoding
  lengths: int [1:3] 4 9 5
  values : int [1:3] 1 11 25

by way of summarizing.

  • Related