Denis
Denis

Reputation: 12077

How do I implement a sliding/lagging window?

So I have used zoo::rollapply() fairly religiously but I don't think it is appropriate for the problem I am looking at. I have a requirement where I would like to implement a shrinking rolling window. So for example, here's some sample data:

v <- data.frame(date=as.Date("2012-1-2") + 0:4, vals=c(1,2,3,4,5))
v
        date vals
1 2012-01-02    1
2 2012-01-03    2
3 2012-01-04    3
4 2012-01-05    4
5 2012-01-06    5

I would like the rolling window to go in date descending order so rev(v$date) for the order and I would like to sum the vals as follows [lagging by 1 every window] (each row below is a window):

5 + 4 + 3 + 2 + 1 = 15
    4 + 3 + 2 + 1 = 10
        3 + 2 + 1 = 6
            2 + 1 = 3
                1 = 1

so I expect my data.frame would be:

#        date vals new_val
#1 2012-01-02    1       1
#2 2012-01-03    2       3
#3 2012-01-04    3       6
#4 2012-01-05    4      10
#5 2012-01-06    5      15

NOTE: Let's say the above example uses the sum(x) function to compute each window. It would be great to generalize this to any function(x). Let's say function(x) { (min(x) + max(x)) * length(x) * sum(x) }

NOTE: I would prefer a base R implementation but other packages that might be applicable would be interesting also

Upvotes: 0

Views: 92

Answers (3)

G. Grothendieck
G. Grothendieck

Reputation: 269586

Use cumsum and rev like this:

transform(v, sum = rev(cumsum(vals)))

giving:

        date vals sum
1 2012-01-02    1  15
2 2012-01-03    2  10
3 2012-01-04    3   6
4 2012-01-05    4   3
5 2012-01-06    5   1

or noting that the width argument can be a vector (see ?rollapply):

library(zoo)

transform(v, sum = rev(rollapplyr(vals, seq_along(vals), sum)))

Upvotes: 1

nsinghphd
nsinghphd

Reputation: 2022

Here is one using sapply

v <- data.frame(date=as.Date("2012-1-2") + 0:4, vals=c(1,2,3,4,5))

v <- data.frame(v[order(rev(v$date)), ],
                  "new_val" = sapply(1:nrow(v), function(x) sum(v[order(rev(v$date)), "vals"][x:5])))

> v
        date vals new_val
5 2012-01-06    5      15
4 2012-01-05    4      10
3 2012-01-04    3       6
2 2012-01-03    2       3
1 2012-01-02    1       1

Upvotes: 1

markus
markus

Reputation: 26343

Try

v$new_val <- cumsum(v$vals)
v
#        date vals new_val
#1 2012-01-02    1       1
#2 2012-01-03    2       3
#3 2012-01-04    3       6
#4 2012-01-05    4      10
#5 2012-01-06    5      15

Upvotes: 3

Related Questions