youngtred
youngtred

Reputation: 155

Apply loop for rollapply windows

I currently have a dataset with 50,000+ rows of data for which I need to find rolling sums. I have completed this using rollaply which has worked perfectly. I need to apply these rolling sums across a range of widths (600, 1200, 1800...6000) which I have done by cut and pasting each line of script and changing the width. While it works, I'd like to tidy my script but applying a loop, or similar, if possible so that once the rollapply function has completed it's first 'pass' at 600 width, it then completes the same with 1200 and so on. Example:

Var1  Var2    Var3
1     11      19
43    12      1
4     13      47
21    14      29
41    15      42
16    16      5
17    17      16
10    18      15
20    19      41
44    20      27

width_2 <- rollapply(x$Var1, FUN = sum, width = 2)
width_3 <- rollapply(x$Var1, FUN = sum, width = 3)
width_4 <- rollapply(x$Var1, FUN = sum, width = 4)

Is there a way to run widths 2, 3, then 4 in a simpler way rather than cut and paste, particularly when I have up to 10 widths, and then need to run this across other cols. Any help would be appreciated.

Upvotes: 3

Views: 180

Answers (2)

Ronak Shah
Ronak Shah

Reputation: 388907

Instead of creating separate vectors in global environment probably you can add these as new columns in the already existing dataframe.

Note that rollaplly(..., FUN = sum) is same as rollsum.

library(dplyr)
library(zoo)

bind_cols(x, purrr::map_dfc(2:4,
 ~x %>% transmute(!!paste0('Var1_roll_', .x) := rollsumr(Var1, .x, fill = NA))))

#   Var1 Var2 Var3 Var1_roll_2 Var1_roll_3 Var1_roll_4
#1     1   11   19          NA          NA          NA
#2    43   12    1          44          NA          NA
#3     4   13   47          47          48          NA
#4    21   14   29          25          68          69
#5    41   15   42          62          66         109
#6    16   16    5          57          78          82
#7    17   17   16          33          74          95
#8    10   18   15          27          43          84
#9    20   19   41          30          47          63
#10   44   20   27          64          74          91

You can use seq to generate the variable window size.

seq(600, 6000, 600)
#[1]  600 1200 1800 2400 3000 3600 4200 4800 5400 6000

Upvotes: 0

akrun
akrun

Reputation: 887048

We can use lapply in base R

lst1 <- lapply(2:4, function(i) rollapply(x$Var1, FUN = sum, width = i))
names(lst1) <- paste0('width_', 2:4)
list2env(lst1, .GlobalEnv)

NOTE: It is not recommended to create multiple objects in the global environment. Instead, the list would be better


Or with a for loop

for(v in 2:4) {
   assign(paste0('width_', v), rollapply(x$Var1, FUN = sum, width = v))  
  }

Create a function to do this for multiple dataset

 f1 <- function(col1, i) {
          rollapply(col1, FUN = sum, width = i)
     }
 
 lapply(x[c('Var1', 'Var2')], function(x) lapply(2:4, function(i)
            f1(x, i)))
               
       

Upvotes: 2

Related Questions