【问题标题】:Result-feeding rolling window or rollapply with cumsum结果-feeding rolling window or rollapply with cumsum
【发布时间】:2020-05-29 20:09:01
【问题描述】:

假设我有以下动物园对象:

x.orig <- read.zoo(data.frame(date=seq(as.Date('2020-01-01'), as.Date('2020-01-10'), 1), v=c(1,2,3,100,4,5,1000,8,8,10)))
2020-01-01 2020-01-02 2020-01-03 2020-01-04 2020-01-05 2020-01-06 2020-01-07 2020-01-08 2020-01-09 2020-01-10 
         1          2          3        100          4          5       1000          8          8         10 

我想计算width=seq_along(x.orig) 的滚动总和,如下所示:

2020-01-01 1
2020-01-02 1 + 2                                   #2020-01-01 + 2020-01-02
2020-01-03 1 + (1 + 2) + 3                         #2020-01-01 + 2020-01-02 + 2020-01-03
2010-01-04 1 + (1 + 2) + (1 + (1 + 2) + 3) + 100   #2020-01-01 + 2020-01-02 + 2020-01-03 + 2020-01-04
...

我想这样做的方法是以某种方式输入结果 x,以便在每个 rollapply 循环之后更新 x,以便下一次 rollapply 迭代在其窗口中获取修改后的值,但我只是不确定如何来写吧……

【问题讨论】:

  • 使用基础 R. cumsum(cumsum(x)) 可能会更容易,而且会更麻烦
  • 实际上我有一周的滚动窗口,所以这就是 cumsum 不起作用的原因,但是是的,我认为它必须有点像 cumsum
  • 也许创建一个函数(x){cumsum(cumsum(x))} 然后滚动一周

标签: r dataframe zoo rollapply


【解决方案1】:

我认为这不是很常见,因此可能不会有此功能,但是您可以使用 Rcpp 破解您自己的快速功能,这是一个示例:

library(data.table)
library(Rcpp)

DT <- data.table(date=seq(as.Date('2020-01-01'), as.Date('2020-01-10'), 1),
                 v=c(1,2,3,100,4,5,1000,8,8,10))
DT[, week := 1:.N %/% 7] # create a week column (you can adapt this to your needs)

# Add your logic to a cpp function
cppFunction("
    IntegerVector roll_cumsum(IntegerVector x) {
        int n = x.size();
        int cumsum = 0;
        IntegerVector y = clone(x);
        for (int i = 0; i < n; ++i) {
            y[i] += cumsum;
            cumsum += y[i];
        }
        return y;
    }
")

DT[, result := roll_cumsum(v), by = week][]

【讨论】:

  • 关于如何嵌入 c++ 函数的酷示例。哇!还没试过……
  • 试一试,在这种情况下它非常简单实用。
【解决方案2】:

一个简单的循环就可以了:

v <- x.orig
for(i in seq_along(v)) v[i] <- sum(head(v, i))

这导致了这个动物园对象:

> v
2020-01-01 2020-01-02 2020-01-03 2020-01-04 2020-01-05 2020-01-06 2020-01-07 
         1          3          7        111        126        253       1501 
2020-01-08 2020-01-09 2020-01-10 
      2010       4020       8042 

滚动应用

如果您想将其包装在宽度为 3 的 rollapplyr 中,请说:

accum <- function(x) { for(i in seq_along(x)) x[i] <- sum(head(x, i)); tail(x, 1) }
rollapplyr(x.orig, 3, accum)

【讨论】:

  • 如果假设我想使用 width=3,我将如何概括这一点?还是自定义宽度列表?
  • 查看添加的 rollapply 部分。
  • 你能解释一下这是做什么的吗?以及它是如何做到的?
  • 关于涉及 v 和 x 的循环,如果我们计算了 v[1], v[2], ..., v[i-1] 那么 v[i] 应该等于它们的总和加上 x[i] 但我们已经将 v 初始化为 x 所以 v[i] 等于 x[i] 因此我们只需将 v[i] 设置为 v[1]+...+v[i] 的总和,它等于总和(头(v,i))。 accum 的工作方式类似,但由于函数退出时 x 会丢失,因此无需保留 x,我们可以使用 x 代替 x 和 v。
【解决方案3】:

这是我的尝试。理想情况下,我想在每次迭代后修改x.orig,但无法让它工作,所以创建了另一个名为latest 的变量。我怀疑这是最好的方法:

library(zoo)

latest <- x.orig
rollapplyr(x.orig, width = seq_along(x.orig), function(x) {
   #browser()
   x <- latest[index(x)]
   v <- sum(x)
   if (!is.na(v))
     latest[last(index(x))] <<- v
   latest[last(index(x))]
})

2020-01-01 2020-01-02 2020-01-03 2020-01-04 2020-01-05 2020-01-06 2020-01-07 2020-01-08 2020-01-09 2020-01-10 
         1          3          7        111        126        253       1501       2010       4020       8042

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-03
    • 2017-12-11
    • 1970-01-01
    • 1970-01-01
    • 2017-12-16
    • 1970-01-01
    • 1970-01-01
    • 2012-08-22
    相关资源
    最近更新 更多