Home > Software design >  How to check every time there are n ascending/descending values in a vector (R)
How to check every time there are n ascending/descending values in a vector (R)

Time:03-02

I have a vector and I want to check every time it contains a sequence of ascending/descending values for length n. All I know so far is that I can use !is.unsorted() and is.unsorted() on a vector to figure out if it is ascending or descending but have no clue on how to do it on every element. Any suggestions would be appreciated!

v <- c(1,2,1,4,5,7,8,10,6,4,2,1,2)
n <- 5

I'm looking to output a vector containing 1, -1 and 0 for ascending, descending and unsorted. In this case, it would output:

[1] 0 0 0 0 0 0 1 1 0 0 0 -1 0

Sorry if this confusing.

CodePudding user response:

You could loop over the vector in length 5 segments and do a case handling if the differences are all less than, greater than zero or anything else.

f <- \(v, n) {
  r <- vapply(seq_along(v)[1:(length(v) - n   1)], \(i) {
    d <- diff(v[(1:n)   i - 1])
    if (all(d < 0)) -1
    else if (all(d > 0)) 1
    else 0
  }, 0)
  return(c(rep(0L, n - 1), r))
}

f(v, 5)
# [1]  0  0  0  0  0  0  1  1  0  0  0 -1  0


## check    
rbind(v, r=f(v, 5))
#   [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
# v    1    2    1    4    5    7    8   10    6     4     2     1     2
# r    0    0    0    0    0    0    1    1    0     0     0    -1     0

Note: R >= 4.1 used.

If you're more familiar with for loops you may also do

res <- vector('integer', length(v) - n   1)
for (i in seq_along(v)[1:(length(v) - n   1)]) {
  d <- diff(v[(1:n)   i - 1])
  if (all(d < 0)) res[i] <- -1
  else if (all(d > 0)) res[i] <- 1
  else res[i] <- 0
}
c(rep(0L, n - 1), res)
# [1]  0  0  0  0  0  0  1  1  0  0  0 -1  0

but it might be slower.

CodePudding user response:

Using data.table package:

d <- data.table::frollsum(sign(diff(v)), n - 1, 0)
c(0, data.table::fcase(d == n - 1, 1, d == 1 - n, -1, default = 0))

[1]  0  0  0  0  0  0  1  1  0  0  0 -1  0

Calculate adjacent difference and take signs (detecting ascending/descending). Then calculate rolling sum and detect when that sum is equal to n-1 (n consecutive ascending elements) or 1-n (n consecutive descending elements).

  •  Tags:  
  • r
  • Related