Applying a function to sequential subvectors of equal size

I am looking for a good and quick way to apply some arbitrary function that works on vectors, such as sum , sequentially into a subvector of consecutive elements of K. Here is one simple example that should very clearly illustrate what I want:

 v <- c(1, 2, 3, 4, 5, 6, 7, 8) v2 <- myapply(v, sum, group_size=3) # v2 should be equal to c(6, 15, 15) 

The function should try to process groups of group_size elements of the given vector and apply the function to each group (considering it as a different vector). In this example, the vector v2 obtained as follows: (1 + 2 + 3) = 6, (4 + 5 + 6) = 15, (7 + 8) = 15. In this case, K did not divide N exactly, so the last group was less than K.

If there is a nicer / faster solution that only works if N is a multiple of K, I would also appreciate it.

+4
source share
3 answers

Try the following:

 library(zoo) rollapply(v, 3, by = 3, sum, partial = TRUE, align = "left") ## [1] 6 15 15 

or

 apply(matrix(c(v, rep(NA, 3 - length(v) %% 3)), 3), 2, sum, na.rm = TRUE) ## [1] 6 15 15 

In addition, in the case of sum latter can be reduced to

 colSums(matrix(c(v, rep(0, 3 - length(v) %% 3)), 3)) 
+6
source

As @Chase notes in the comment, you can create your own grouping variable and then use it. Wrapping this process into a function will look like

 myapply <- function(v, fun, group_size=1) { unname(tapply(v, (seq_along(v)-1) %/% group_size, fun)) } 

which gives your results

 > myapply(v, sum, group_size=3) [1] 6 15 15 

Note that this does not require v be a multiple of group_size .

+2
source

You can also try. This works well, even if you want to include overlapping intervals controlled by and as a bonus, return the intervals over which each value is produced:

 library (gtools) v2 <- running(v, fun=sum, width=3, align="left", allow.fewer=TRUE, by=3) v2 1:3 4:6 7:8 6 15 15 
0
source

All Articles