【问题标题】:Apply loop for rollapply windows为 rollapply 窗口应用循环
【发布时间】:2020-10-01 00:37:52
【问题描述】:

我目前有一个包含 50,000 多行数据的数据集,我需要为其查找滚动总和。我已经使用rollaply 完成了这项工作,效果很好。我需要将这些滚动总和应用于一系列宽度(600、1200、1800...6000),我通过剪切和粘贴每行脚本并更改宽度来完成。虽然它可以工作,但我想整理我的脚本,但如果可能的话,应用一个循环或类似的方法,以便一旦 rollapply 函数完成它在 600 宽度处的第一次“通过”,然后以 1200 完成相同的操作,等等在。示例:

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)

有没有办法以更简单的方式运行宽度 2、3、4,而不是剪切和粘贴,特别是当我有多达 10 个宽度,然后需要跨其他列运行时。任何帮助将不胜感激。

【问题讨论】:

    标签: r zoo


    【解决方案1】:

    我们可以在base R中使用lapply

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

    注意:不建议在全局环境中创建多个对象。相反,list 会更好


    或者使用for 循环

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

    创建一个函数来为多个数据集执行此操作

     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)))
                   
           
    

    【讨论】:

    • 鉴于我的实际窗口是 600 的倍数,这会变成:for(v in 600:6000) { assign(paste0('width_', v), rollapply(x$Var1, FUN = sum, width = v))
    • 我刚刚尝试了上面的评论,虽然它适用于示例,但当我将它外推到我的实际数据时,它会将函数应用于每个宽度 600:6000。我可以使这项工作仅适用于 600 的倍数,即 600、1200、1800、2400....6000?编辑:添加了一个简单的宽度向量 c(600, 1200, 1800....) 并完美运行
    • rollapply 已经适用于每一列,因此不需要额外的列。
    【解决方案2】:

    您可以将这些作为新列添加到现有数据框中,而不是在全局环境中创建单独的向量。

    注意rollaplly(..., FUN = sum)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
    

    您可以使用seq 来生成可变窗口大小。

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

    【讨论】:

    • 此解决方案比仅使用 lapply() 或也可以在 SO 中的其他答案中找到的循环更适合该问题!
    猜你喜欢
    • 2012-10-20
    • 2011-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多