2

I am using rollapply (from the zoo package) in R to get rolling mean values for a series of rows in a data frame.

For each row, where the focal row is x I am trying to get a number of means. I can do this with a loop but it's slow, and I try to avoid loops.

The aim is to get rolling means for 4 different specifications:

  1. mean of row x, x-1, and x+1: "Rat3"
  2. mean of row x through row x+7: "RatE"
  3. mean of row x+8 through row x+15: "RatL"
  4. mean of row x through row x+15: "RatJ"

Using loops I can get all of these, but its slow:

tempDF = data.frame(sample(c("A","B"), replace = T, size = 100),rnorm(100,10,2))
colnames(tempDF) = c("Cohort","Rat")

for(i in 1:length(tempDF$Cohort)){
       tempDF$Rat3[i] = (mean(tempDF$Rat[(i-1):(i+1 )], na.rm = FALSE)) 
       tempDF$RatE[i] = (mean(tempDF$Rat[(i+0):(i+7 )], na.rm = FALSE)) 
       tempDF$RatL[i] = (mean(tempDF$Rat[(i+8):(i+15)], na.rm = FALSE)) 
       tempDF$RatJ[i] = (mean(tempDF$Rat[(i+0):(i+15)], na.rm = FALSE)) 
}

I can get the Rat3 using the rollapply function:

tempDF$Rat3 = c(0,rollapply(tempDF$Rat, 3, FUN = mean, by = 1),0)

But I'm stuck in how to modify this to make it not centre around the value $x$, instead using $x$ (or $x+8$) as a starting point for the rolling average. How can I set the rollapply function to manipulate the way it "moves" the rolling average window?

Here's an inelegant solution:

tempDF$RatE = c(0,0,0,0,rollapply(tempDF$Rat, 8, FUN = mean, by = 1),0,0,0)
tempDF$RatE = c(tempDF$RatE[5:(length(tempDF$RatE)-3)],rep("0",times=7))
rg255
  • 4,119
  • 3
  • 22
  • 40

2 Answers2

1

I think you are looking for the align parameter, which can be set to 'center', 'left' or 'right', but defaults to 'left'.

As an aside, did you pre-allocate the four result vectors? That can often make loops slow.

Darren Cook
  • 27,837
  • 13
  • 117
  • 217
0

The two solutions in the question for Rat3 are not the same. Rat3[1] is mean(Rat[1:2]) in the first Rat3 solution (that uses the loop) and is 0 in the second Rat3 solution (that uses rollapply). Assuming you want to zero fill (as in the second solution):

# roll is convenience function so we don't have to repeat some args 4 times
roll <- function(...) rollapply(FUN = mean, na.rm = FALSE, fill = 0, ...)
transform(tempDF,
            Rat3 = roll(Rat, 3),
            RatE = roll(Rat, 8, align = "left"),
            RatL = roll(Rat, list(8:15)),
            RatJ = roll(Rat, 16, align = "left")
)

This would also work:

transform(tempDF,
            Rat3 = roll(Rat, list(c(-1, 0, 1))),
            RatE = roll(Rat, list(0:7)),
            RatL = roll(Rat, list(8:15)),
            RatJ = roll(Rat, list(0:15))
)

See ?rollapply for detailed information on the rollapply arguments.

G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341