使 rollApply() 跳过 n 步 - R

Posted

技术标签:

【中文标题】使 rollApply() 跳过 n 步 - R【英文标题】:Making rollApply() skip n steps - R 【发布时间】:2021-12-08 11:24:51 【问题描述】:

以下是我尝试的最小可重现示例。简要说明,我使用 rowr 包中的 rollApply 来计算滚动窗口上的函数,并同时使用两列中的数据。如果可能的话,我想在每次在新窗口上计算函数时跳过 n 步。我将尝试在下面的示例中阐明我的意思。

这是示例数据:

df1 <- tibble(
  x = c(1:9), 
  y = c(1:9), 
  Date = as.Date(c("2015-08-08", "2015-08-15", "2015-08-22", 
                   "2015-08-29","2015-09-05", "2015-09-12", "2015-09-19", 
                   "2015-09-26", "2015-10-03"))
)

以下是示例函数:

calc_ex <- function(y)
  
  sum(y[,1] + y[,2])


roll_calc_ex <- function(y)
  
  vec <- c(rep(NA, 2), rowr::rollApply(y, calc_ex, window = 3, minimum = 3))
  
  y <- y %>%
    mutate(estimate = vec)
           

  return(y)

将函数roll_calc_ex()应用于df1,得到如下输出:

> roll_calc_ex(df1)
# A tibble: 9 x 4
       x     y Date       estimate
   <int> <int> <date>        <int>
 1     1     1 2015-08-08       NA
 2     2     2 2015-08-15       NA
 3     3     3 2015-08-22       12
 4     4     4 2015-08-29       18
 5     5     5 2015-09-05       24
 6     6     6 2015-09-12       30
 7     7     7 2015-09-19       36
 8     8     8 2015-09-26       42
 9     9     9 2015-10-03       48

理想情况下,我希望有一个滚动窗口跳过 n 步,例如 n=2,以产生以下输出:

# A tibble: 9 x 4
       x     y Date       estimate
   <int> <int> <date>        <int>
 1     1     1 2015-08-08       NA
 2     2     2 2015-08-15       NA
 3     3     3 2015-08-22       12
 4     4     4 2015-08-29       NA
 5     5     5 2015-09-05       NA
 6     6     6 2015-09-12       30
 7     7     7 2015-09-19       NA
 8     8     8 2015-09-26       NA
 9     9     9 2015-10-03       48

或者,不是为跳过的每一行返回 NA,而是可以填充先前计算的数字(我计划稍后使用 tidyverse 中的 fill() 来做)。

如果可以使用 zoo 包中的 rollapply() 来解决这个问题,那也很有趣。我只使用 rowr::rollApply() 因为我需要将该函数同时应用于两列。我知道可以使用“runner”包中的 runner(),但在我更复杂的问题中,我需要运行并行计算。我正在使用 furrr 包进行并行化,我的代码适用于 rollApply,但不适用于 runner()。这里解释了我遇到的跑步者问题:Problem with parallelization using furrr [and runner::runner() ] in R。

感谢所有花时间阅读这篇文章的人。任何帮助将不胜感激。

【问题讨论】:

您是否尝试过使用滑块包?有一个 step 参数实现了这种行为 【参考方案1】:

1) rowr 包已从 CRAN 中删除,但我们可以使用来自 zoo 的 rollapplyr(如 rollapply 但最后的 r 表示默认为右对齐)一个 by.column= 参数来指定是逐列执行处理 (TRUE) 还是一次传递所有列 (FALSE) 和一个导致跳过的 by= 参数。

library(dplyr)
library(zoo)

mutate(df1, roll = 
  rollapplyr(cbind(x, y), 3, calc_ex, fill = NA, by.column = FALSE, by = 2)
)

给予:

  x y       Date roll
1 1 1 2015-08-08   NA
2 2 2 2015-08-15   NA
3 3 3 2015-08-22   12
4 4 4 2015-08-29   NA
5 5 5 2015-09-05   24
6 6 6 2015-09-12   NA
7 7 7 2015-09-19   36
8 8 8 2015-09-26   NA
9 9 9 2015-10-03   48

2) 也可以使用复数运算:

f <- function(v) calc_ex(cbind(Re(v), Im(v)))
mutate(df1, roll = rollapplyr(x + y * 1i, 3, f, fill = NA, by = 2))

3) 如果我们研究 call_ex 那么它可以写成(虽然这不能概括):

mutate(df1, roll = rollapplyr(x + y, 3, sum, fill = NA, by = 2))

4)我们也可以考虑使用动物园对象而不是数据框:

z <- read.zoo(df1, index = "Date")
merge(z, roll = rollapplyr(z, 3, calc_ex, by.column = FALSE, by = 2))

【讨论】:

【参考方案2】:

如果我们要使用滑块包

library(tidyverse)
library(slider)


df1 <- tibble(
  x = c(1:9), 
  y = c(1:9), 
  Date = as.Date(c("2015-08-08", "2015-08-15", "2015-08-22", 
                   "2015-08-29","2015-09-05", "2015-09-12", "2015-09-19", 
                   "2015-09-26", "2015-10-03")))

df1 |> 
  mutate(rolling_sum = slide2_dbl(.x = x,.y = y,.f = sum,
                                  .step = 3,.before = 2,.complete   = T
))
#> # A tibble: 9 x 4
#>       x     y Date       rolling_sum
#>   <int> <int> <date>           <dbl>
#> 1     1     1 2015-08-08          NA
#> 2     2     2 2015-08-15          NA
#> 3     3     3 2015-08-22          12
#> 4     4     4 2015-08-29          NA
#> 5     5     5 2015-09-05          NA
#> 6     6     6 2015-09-12          30
#> 7     7     7 2015-09-19          NA
#> 8     8     8 2015-09-26          NA
#> 9     9     9 2015-10-03          48

由reprex package (v2.0.1) 于 2021 年 10 月 21 日创建

【讨论】:

以上是关于使 rollApply() 跳过 n 步 - R的主要内容,如果未能解决你的问题,请参考以下文章

CAPM.beta rollapply

如何使绘制的图像居中?

在while循环中使用if语句使R跳过某些索引值

R语言使用zoo包中的rollapply函数计算两个时间序列数据列之间的滚动相关性(Rolling correlations)例如,计算两种商品销售额之间的3个月的滚动相关性

从 gdbinit 脚本单步执行时如何设置跳过不感兴趣的函数?

问题解决:The connection to the server xxxxx:6443 was refused - did you specify the right host or port?