Reproducible example:
set.seed(1)
A <- round(runif(12, min = 1, max = 5))
> A
[1] 1 2 2 4 3 4 3 4 5 3 4 5
expectedResult <- c(max(A[1], A[4]), max(A[2], A[5]), max(A[3], A[6]), max(A[7], A[10]), max(A[8], A[11]), max(A[9], A[12]))
> expectedResult
[1] 4 3 4 3 4 5
Each A needs to be considered as a collection of segments with 6 elements. For example, A here has 2 segments such as A[1:6] and A[7:12]. For each segment, the first 3 elements are compared with the next 3 elements. Therefore I need to take max(A[1],A[4])
, max(A[2], A[5])
, max(A[2], A[5])
, max(A[3], A[6])
, max(A[7], A[10])
, max(A[8], A[11])
, max(A[9], A[12])
.
My original vector has way more elements than this example and therefore I need a much simpler approach to do this. In addition, speed is also a factor for the original calculation and therefore looking for a fast solution as well.
We could create a function to split
the vector by 'n' elements, loop over the list
, create a matrix
with nrow
specified as 2, use pmax
to do elementwise
max after converting to data.frame
, return the output by unlist
ing the list
f1 <- function(vec, n) {
lst1 <- split(vec, as.integer(gl(length(vec), n, length(vec))))
unname(unlist(lapply(lst1, function(x)
do.call(pmax, as.data.frame(t(matrix(x, nrow = 2, byrow = TRUE)))))))
}
-output
> f1(A, 6)
[1] 4 3 4 3 4 5
If the length is not a multiple of 3 or 6, another option is to do a group by operation with tapply
after splitting
unname(unlist(lapply(split(A, as.integer(gl(length(A), 6,
length(A)))), function(x) tapply(x, (seq_along(x)-1) %% 3 + 1, FUN = max))))
[1] 4 3 4 3 4 5
A <- c(1, 2, 2, 4, 3, 4, 3, 4, 5, 3, 4, 5)