Home > Software design >  denote the occasion in which a threshold is exceed three consecutive columns in a row over a list of
denote the occasion in which a threshold is exceed three consecutive columns in a row over a list of

Time:12-29

I have a list of matrices. For each matrix within the list I am attempting to denote when a value is < 100 for three consecutive occasions. Ultimately all I need is a 1 for each matrix if the event occurred three times in a row at any point along the sequence, or a 0 if it did not. the code I am providing is higher resolution but I can reduce it down later. Below is the code I have thus far. For some reason it is marking a 1 just at the occurrence of < 100 and not 3 consecutive appearances. I presume the lead function is inappropriate but am stuck at the moment. Am sure a seq_along forloop could be used but am trying to keep it functional. Thanks

set.seed(24)
list_of_matrices <- replicate(100, matrix(rnorm(1*51), nrow = 1), simplify = FALSE)
test<- lapply(list_of_matrices,function(x){ifelse(x & lead(x,1) & lead(x, 2) < 100, 1, NA)})

CodePudding user response:

We may use rle here

out <- lapply(list_of_matrices, function(m) {
   t(apply(m, 1, function(u)   {
         rl <- rle(u < 100)
         rl$values[(rl$lengths < 3) & rl$values] <- FALSE
         as.integer(inverse.rle(rl))
}))
})

-output

> out[[1]]
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    0    0    0    0    0    0    0    0    0     0
[2,]    0    0    0    0    1    1    1    1    1     0
[3,]    1    1    1    1    1    0    1    1    1     0
[4,]    0    0    0    0    0    0    0    0    0     0
[5,]    0    0    0    0    0    0    0    0    0     0

> list_of_matrices[[1]]
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]  118  114   88  112  100  116  105  119  112   114
[2,]   98  108   87  116   87   97   85   86   83   100
[3,]   87   89   96   95   97  112   85   80   94   105
[4,]  102  105   87  100   91  116  114   85   82   120
[5,]  113  120   92   91  110   99  112  118   93    80

If it is a list of vectors, we can directly apply the rle by looping over the list

lapply(lst1, function(u) {
   rl <- rle(u < 100)
   rl$values[(rl$lengths < 3) & rl$values] <- FALSE      
    as.integer(inverse.rle(rl))
  })

data

set.seed(24)
list_of_matrices <- replicate(3, matrix(sample(80:120, 5 * 10, 
  replace = TRUE), ncol = 10, nrow = 5), simplify = FALSE)
  • Related