0
votes

I am trying to create a rolling computation using rollapply on a window that slides down the columns of an xts data frame. For example, suppose I define an xts object:

df1 <- data.frame(A = c(1,2,3,4,5,6,7,8,9),
              B = c(3,4,5,6,7,8,9,10,11))
dfxts <- xts(df1, order.by = as.Date(c(30,31,32,33,34,35,36,37,38)))

This gives the xts function:

           A  B
1970-01-31 1  3
1970-02-01 2  4
1970-02-02 3  5
1970-02-03 4  6
1970-02-04 5  7
1970-02-05 6  8
1970-02-06 7  9
1970-02-07 8 10
1970-02-08 9 11

As I understand the width parameter, it defines the length of a sliding window where some operation takes place, e.g., a mean operation (although I am not clear about ‘width').

Say I wanted to create a rolling operation on a window of width 3 where I add the 2nd and 3rd elements of the window at each position. At each position of the window I want to add x(2) + x(3). I would get:

           A  B
1970-01-31 NA NA
1970-02-01 NA NA
1970-02-02 5  9
1970-02-03 7  11
1970-02-04 9  13
1970-02-05 11 15
1970-02-06 13 17
1970-02-07 15 19
1970-02-08 17 21

I try to implement this with:

 rollapply(dfxts, width = 3, FUN=function(x) x(2)+x(3), align = "right")

and I get the error:

"Error during wrapup: could not find function “x"

I think I misunderstand how to use rollapply, how to implement an anonymous function, or both.

2

2 Answers

1
votes

Just a slight change to your rollapply (sum(x[2],x[3]) instead of x(2)+x(3)) and it works:

rollapply(dfxts, width = 3, FUN=function(x) sum(x[2],x[3]), align = "right")

Here is the output I get:

#            A  B
#1970-01-31 NA NA
#1970-02-01 NA NA
#1970-02-02  5  9
#1970-02-03  7 11
#1970-02-04  9 13
#1970-02-05 11 15
#1970-02-06 13 17
#1970-02-07 15 19
#1970-02-08 17 21

Hope it helps.

1
votes

I am not sure if you can apply the rollapply to the entire dataframe. You can apply it to every column separately with lapply and since you want sum of second and third element you can reduce the width as 2 instead

library(zoo)
lapply(dfxts, function(x) rollapply(x, width = 2, FUN=sum))


#$A
#            A
#1970-01-31 NA
#1970-02-01  3
#1970-02-02  5
#1970-02-03  7
#1970-02-04  9
#1970-02-05 11
#1970-02-06 13
#1970-02-07 15
#1970-02-08 17

#$B
#            B
#1970-01-31 NA
#1970-02-01  7
#1970-02-02  9
#1970-02-03 11
#1970-02-04 13
#1970-02-05 15
#1970-02-06 17
#1970-02-07 19
#1970-02-08 21

If for some reason you have to keep width as 3 only and can't change it then we can do

lapply(dfxts, function(x) rollapply(x, width = 3, FUN=function(y) sum(y[2],y[3])))

which will give the same output except first two values would be NA instead of one.


EDIT

As mentioned in the comments the actual function to be applied is more complicated then the one which is presented and it would require using custom functions rather than in-built functions we can use coredata to get the actual data and then apply our function accordingly.

So in the given example, we could do

rollapply(dfxts, width = 3, FUN=function(x) coredata(x[2]) +  coredata(x[3]))

However, for a more general approach , we can call coredata only once and then use them the way we want. so if we want to apply operation 5*x(5) - 8*x(7) + x(15), we could do

rollapply(dfxts, width = 15, FUN=function(x) {
          vals <- coredata(x)
          5*vals[5] - 8*vals[7] + vals[15]
})