Question:
I have a 1:50
vector and I need to perform a moving sum (equal to the moving average), that is, in the case of the last 5 observations, the new vector would be c(sum(1:5), sum(2:6), sum(3:7), ..., sum(45:49), sum(46:50))
.
The aggregate function has example aggregate(presidents, nfrequency = 1, FUN = weighted.mean, w = c(1, 1, 0.5, 1))
which was the closest I got to the solution without using a for
Answer:
I know of two good packages to do this. The zoo
(as Rui mentioned in the comment) and RcppRoll
.
> zoo::rollsum(1:20, k = 5)
[1] 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90
> RcppRoll::roll_sum(1:20, n = 5)
[1] 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90
In terms of performance, RcppRoll
is much faster:
> bench::mark(
+ zoo::rollsum(1:50, k = 5),
+ RcppRoll::roll_sum(1:50, n = 5)
+ )
# A tibble: 2 x 14
expression min mean median max `itr/sec` mem_alloc n_gc n_itr total_time result memory time gc
<chr> <bch:t> <bch:tm> <bch:t> <bch:> <dbl> <bch:byt> <dbl> <int> <bch:tm> <list> <list> <lis> <lis>
1 zoo::roll… 909.4µs 3.45ms 1.71ms 40.3ms 290. 18.91KB 0 155 535ms <int … <Rpro… <bch… <tib…
2 RcppRoll:… 40.5µs 150.75µs 89.49µs 14.6ms 6634. 3.34KB 0 3316 500ms <dbl … <Rpro… <bch… <tib…