Search code examples
rlagrunner

Highest value since - finding the interval in R


I'm working right now at Forex project and I found a problem on my way. I'm trying to find when was the last time when current value was this high or this low.

At the beginning I was trying to do that this way:

length(c(1:10)) - max(which(c(1:10) <= 6))

i.e. if we consider vector c(1:10,6) the output of the function above would be 4. Which would mean that 6 is the highest value since 4 intervals.

So my goal now was to implement above function into dplyr::mutate method. That's where things got out of hand... With the runner function from runner package I was able to create tibble with values and their lags:

# A tibble: 11 x 2
   value `runner(value, lag = 1)`
   <dbl> <list>                  
 1     9 <dbl [0]>               
 2     7 <dbl [1]>               
 3     4 <dbl [2]>               
 4     1 <dbl [3]>               
 5     5 <dbl [4]>               
 6     2 <dbl [5]>               
 7     5 <dbl [6]>               
 8     4 <dbl [7]>               
 9     1 <dbl [8]>               
10     6 <dbl [9]>               
11     6 <dbl [10]>  

But then no matter what I have tried I can't relate value number at current list to a runner column. I was trying things like purrr:map or sapply but is still would refer to whole column. I also trying to implement dplyr::rowWise but it didn't help me either.

I feel like I am going around the solution and that it can clearly be done easily. If there is some magic package that would help me to solve my issue quickly I would be more than thankful for help. But I would still like to know if there is a way to relate in that kind of situation to the current row value instead of whole column.

I was also trying to close this into one tidy user made function so that would be another plus if you could point me in that direction.


Solution

  • I have found the solution thanks to the @allan-cameron 's answer:

    last_below <- function(x) {
      sapply(
        seq(x), 
        function(i) {
          (i - tail(which(x[0:(i-1)] <= x[i]),1))[1]
        }
      )
    }
    

    By calling:

    a %>% 
      mutate(b = last_below(value)) 
    

    I get the output:

    # A tibble: 11 x 2
       value     b
       <dbl> <int>
     1     9    NA
     2     7    NA
     3     4    NA
     4     1    NA
     5     5     1
     6     2     2
     7     5     1
     8     4     2
     9     1     5
    10     6     1
    11     6     1