R - 产品过度轧制的总和 windows(四分之一)
R - Cumsum of product over rolling windows (quarters)
我想计算value
列的累计和,有特殊要求。在一个季度(= 3 个月)过去后,value
会折旧一个常数,比如 0.9
。这意味着,它现在仅将其原始值的 90% 计入 cumsum。当另一个季度过去时,重复此操作,即 90% 再次乘以常数 (0.9)(这等于原始值 * 0.9^2)。每经过一个季度,都会重复此过程,因此一年后原始值 运行 的 0.9^4 进入 cumsum,两年后 0.9^8,依此类推。完整的原始值仅在其日期变量之后的第一季度完全计入 cumsum。
示例:01/15 的值 100 将添加到 cumsum 100
直到 04/15,100*0.9=90
在 04/15 和 07/15 之间,100*0.9^2=81
在 07 月 15 日和 10 月 15 日之间,依此类推,请参阅 MRE 的 desired_output
列。
MRE:
df <- tribble(~date, ~value,~country,~desired_output,
"2017-01-01", 2, "US", 2,
"2017-01-05", 2, "UK", 8,
"2017-01-05", 4, "US", 8,
"2017-04-01", 5, "IT", 12.8, # only the first observation is older than a quarter so calculate as (2*0.9+2+4+5)
"2017-04-03", 3, "US", 115.8, #(2*0.9+2+4+5+3+100)
"2017-04-03", 100, "US", 115.8,
"2017-04-11", 20, "UK", 135.2, # now the first three observations are older than a quarter (8*0.9+5+3+100+20)
"2017-04-15", 6, "US", 141.2,
"2017-07-02", 30, "US", 170.52, # now the first observation is older than two quarters and the second, third, and forth observation are older than a quarter (2*0.9^2+11*0.9+3+100+20+6+30)
"2017-10-12", 4, "UK", 151.912, # ((2+2+4)*0.9^3+(5+3+100+20)*0.9^2+(6+30)*0.9+4+6)
"2017-10-12", 6, "IT", 151.912) # (8*0.9^3+128*0.9^2+36*0.9+10)
假设常量值为 0.9,日期格式为 %Y-%b-%d
.
进一步澄清问题的伪代码:
取每个 quarter/3 月的总和(从当前行的 date
开始)
根据这段时间到当前行日期的距离对常数求幂(例如,如果季度是从
今天)
将此调整后常数乘以相应季度(3 个月期间)的总和
取所有季度 cumsum 的 cumsum
在下一步中,我还想通过分组变量(例如 country
)获取这个特定的 cumsum。
这里有一个选项:
DT[, do :=
.SD[.SD, on=.(date<=date), by=.EACHI, {
nqtr <- floor(pmax(0, i.date - x.date) / 90)
sum(value * 0.9^nqtr)
}]$V1
]
输出:
date value country desired_output do
1: 2017-01-01 2 US 2.000 2.000
2: 2017-01-05 2 UK 8.000 8.000
3: 2017-01-05 4 US 8.000 8.000
4: 2017-04-01 5 IT 12.800 12.800
5: 2017-04-03 3 US 115.800 115.800
6: 2017-04-03 100 US 115.800 115.800
7: 2017-04-11 20 UK 135.200 135.200
8: 2017-04-15 6 US 141.200 141.200
9: 2017-07-02 30 US 170.520 160.220
10: 2017-10-12 4 UK 151.912 151.372
11: 2017-10-12 6 IT 151.912 151.372
区别在于我们如何定义季度。我用的是90d。如果3m真的很重要,我会更新post。例如,在 2017 年 7 月 2 日,使用 90 天时,第 2-6 行是 1 季度前,而在您的 OP 中,使用 3m 时只有第 2-4 行是 1 季度前。
数据:
library(data.table)
DT <- fread('date,value,country,desired_output
"2017-01-01", 2, "US", 2
"2017-01-05", 2, "UK", 8
"2017-01-05", 4, "US", 8
"2017-04-01", 5, "IT", 12.8
"2017-04-03", 3, "US", 115.8
"2017-04-03", 100, "US", 115.8
"2017-04-11", 20, "UK", 135.2
"2017-04-15", 6, "US", 141.2
"2017-07-02", 30, "US", 170.52
"2017-10-12", 4, "UK", 151.912
"2017-10-12", 6, "IT", 151.912')
DT[, date := as.IDate(date, format="%Y-%m-%d")]
处理 3m 和国家要求:
DT[, do :=
.SD[.SD, on=.(country, date<=date), by=.EACHI, {
vec <- rev(seq(i.date, min(x.date)-93L, by="-1 quarter"))
itvl <- findInterval(x.date, vec, rightmost.closed=TRUE)
nqtr <- length(vec) - itvl - 1L
sum(value * 0.9^nqtr)
}]$V1
]
输出:
date value country desired_output do
1: 2017-01-01 2 US 2.000 2.000
2: 2017-01-05 2 UK 8.000 8.000
3: 2017-01-05 4 US 8.000 8.000
4: 2017-04-01 5 IT 12.800 13.000
5: 2017-04-03 3 US 115.800 115.800
6: 2017-04-03 100 US 115.800 115.800
7: 2017-04-11 20 UK 135.200 135.200
8: 2017-04-15 6 US 141.200 141.200
9: 2017-07-02 30 US 170.520 170.520
10: 2017-10-12 4 UK 151.912 151.912
11: 2017-10-12 6 IT 151.912 151.912
我想计算value
列的累计和,有特殊要求。在一个季度(= 3 个月)过去后,value
会折旧一个常数,比如 0.9
。这意味着,它现在仅将其原始值的 90% 计入 cumsum。当另一个季度过去时,重复此操作,即 90% 再次乘以常数 (0.9)(这等于原始值 * 0.9^2)。每经过一个季度,都会重复此过程,因此一年后原始值 运行 的 0.9^4 进入 cumsum,两年后 0.9^8,依此类推。完整的原始值仅在其日期变量之后的第一季度完全计入 cumsum。
示例:01/15 的值 100 将添加到 cumsum 100
直到 04/15,100*0.9=90
在 04/15 和 07/15 之间,100*0.9^2=81
在 07 月 15 日和 10 月 15 日之间,依此类推,请参阅 MRE 的 desired_output
列。
MRE:
df <- tribble(~date, ~value,~country,~desired_output,
"2017-01-01", 2, "US", 2,
"2017-01-05", 2, "UK", 8,
"2017-01-05", 4, "US", 8,
"2017-04-01", 5, "IT", 12.8, # only the first observation is older than a quarter so calculate as (2*0.9+2+4+5)
"2017-04-03", 3, "US", 115.8, #(2*0.9+2+4+5+3+100)
"2017-04-03", 100, "US", 115.8,
"2017-04-11", 20, "UK", 135.2, # now the first three observations are older than a quarter (8*0.9+5+3+100+20)
"2017-04-15", 6, "US", 141.2,
"2017-07-02", 30, "US", 170.52, # now the first observation is older than two quarters and the second, third, and forth observation are older than a quarter (2*0.9^2+11*0.9+3+100+20+6+30)
"2017-10-12", 4, "UK", 151.912, # ((2+2+4)*0.9^3+(5+3+100+20)*0.9^2+(6+30)*0.9+4+6)
"2017-10-12", 6, "IT", 151.912) # (8*0.9^3+128*0.9^2+36*0.9+10)
假设常量值为 0.9,日期格式为 %Y-%b-%d
.
进一步澄清问题的伪代码:
取每个 quarter/3 月的总和(从当前行的
date
开始)根据这段时间到当前行日期的距离对常数求幂(例如,如果季度是从 今天)
将此调整后常数乘以相应季度(3 个月期间)的总和
取所有季度 cumsum 的 cumsum
在下一步中,我还想通过分组变量(例如 country
)获取这个特定的 cumsum。
这里有一个选项:
DT[, do :=
.SD[.SD, on=.(date<=date), by=.EACHI, {
nqtr <- floor(pmax(0, i.date - x.date) / 90)
sum(value * 0.9^nqtr)
}]$V1
]
输出:
date value country desired_output do
1: 2017-01-01 2 US 2.000 2.000
2: 2017-01-05 2 UK 8.000 8.000
3: 2017-01-05 4 US 8.000 8.000
4: 2017-04-01 5 IT 12.800 12.800
5: 2017-04-03 3 US 115.800 115.800
6: 2017-04-03 100 US 115.800 115.800
7: 2017-04-11 20 UK 135.200 135.200
8: 2017-04-15 6 US 141.200 141.200
9: 2017-07-02 30 US 170.520 160.220
10: 2017-10-12 4 UK 151.912 151.372
11: 2017-10-12 6 IT 151.912 151.372
区别在于我们如何定义季度。我用的是90d。如果3m真的很重要,我会更新post。例如,在 2017 年 7 月 2 日,使用 90 天时,第 2-6 行是 1 季度前,而在您的 OP 中,使用 3m 时只有第 2-4 行是 1 季度前。
数据:
library(data.table)
DT <- fread('date,value,country,desired_output
"2017-01-01", 2, "US", 2
"2017-01-05", 2, "UK", 8
"2017-01-05", 4, "US", 8
"2017-04-01", 5, "IT", 12.8
"2017-04-03", 3, "US", 115.8
"2017-04-03", 100, "US", 115.8
"2017-04-11", 20, "UK", 135.2
"2017-04-15", 6, "US", 141.2
"2017-07-02", 30, "US", 170.52
"2017-10-12", 4, "UK", 151.912
"2017-10-12", 6, "IT", 151.912')
DT[, date := as.IDate(date, format="%Y-%m-%d")]
处理 3m 和国家要求:
DT[, do :=
.SD[.SD, on=.(country, date<=date), by=.EACHI, {
vec <- rev(seq(i.date, min(x.date)-93L, by="-1 quarter"))
itvl <- findInterval(x.date, vec, rightmost.closed=TRUE)
nqtr <- length(vec) - itvl - 1L
sum(value * 0.9^nqtr)
}]$V1
]
输出:
date value country desired_output do
1: 2017-01-01 2 US 2.000 2.000
2: 2017-01-05 2 UK 8.000 8.000
3: 2017-01-05 4 US 8.000 8.000
4: 2017-04-01 5 IT 12.800 13.000
5: 2017-04-03 3 US 115.800 115.800
6: 2017-04-03 100 US 115.800 115.800
7: 2017-04-11 20 UK 135.200 135.200
8: 2017-04-15 6 US 141.200 141.200
9: 2017-07-02 30 US 170.520 170.520
10: 2017-10-12 4 UK 151.912 151.912
11: 2017-10-12 6 IT 151.912 151.912