result-feeding rolling window 或 rollapply with cumsum
Result-feeding rolling window or rollapply with cumsum
假设我有以下动物园对象:
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 迭代在其 window 中获取修改后的值但我就是不知道怎么写...
这是我的尝试。理想情况下,我想在每次迭代后修改 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
我不认为这很常见,所以可能不会有此功能,但是您可以使用 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][]
一个简单的循环就可以做到:
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
rollapply
如果你想将其包装在宽度为 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)
假设我有以下动物园对象:
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 迭代在其 window 中获取修改后的值但我就是不知道怎么写...
这是我的尝试。理想情况下,我想在每次迭代后修改 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
我不认为这很常见,所以可能不会有此功能,但是您可以使用 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][]
一个简单的循环就可以做到:
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
rollapply
如果你想将其包装在宽度为 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)