R语言 如果宽度取决于总和本身,如何进行滚动求和?

vfh0ocws  于 2023-02-26  发布在  其他
关注(0)|答案(1)|浏览(164)

我有一个包含"amount"列的大规模数据集,每当它超过累积和阈值时,我就想按它分组,但是,我目前的解决方案太慢,使它不可行。
示例:

library(data.table)
dt <- data.table(amount = c(0.009288, 0.189386, 0.071265, 0.137387, 0.032742, 0.000003, 0.071265, 0.122247, 0.124920, 0.032743))

阈值为0.2时,我寻找的"指标"应该是:
Expected output
使得我可以使用该指示符通过累积和来分组/选择直到并包括阈值观察的观察。
我尝试过循环遍历"cumsum"列,并尝试使用逻辑向量,但由于我需要在每个cumsum之后提取下一个"起点",或者重置总和,因此速度太慢:

to_add <- 0.2
dt[, cumSum:=cumsum(amount)]
dt[, indicator:=as.numeric(NA)]
threshold <- copy(to_add)
for(i in 1:nrow(dt)) {
  print(i)
  if(threshold > max(dt$cumSum)) break
  amount_t <- dt[cumSum >= threshold]$cumSum[1]
  dt[cumSum <= amount_t & is.na(indicator), indicator:=i]
  threshold <- amount_t + to_add
}
dt[is.na(indicator), indicator:=i]
jm81lzqq

jm81lzqq1#

base中使用Reduce,我们可以在累加行时设置一个条件,以查找总和何时超过阈值。

library(data.table)

dt[, `:=`(csum = cumsum(amount),
          id = shift(cumsum(Reduce(function(lag_csum, r_val){
                                      ifelse(lag_csum < 0.2, lag_csum + r_val , r_val)}, 
                    amount, accumulate = TRUE) > 0.2), fill = 0) + 1)][]
#>       amount     csum id
#>  1: 0.009288 0.009288  1
#>  2: 0.189386 0.198674  1
#>  3: 0.071265 0.269939  1
#>  4: 0.137387 0.407326  2
#>  5: 0.032742 0.440068  2
#>  6: 0.000003 0.440071  2
#>  7: 0.071265 0.511336  2
#>  8: 0.122247 0.633583  3
#>  9: 0.124920 0.758503  3
#> 10: 0.032743 0.791246  4

或使用purrr:accumulate

dt[, `:=`(csum = cumsum(amount),
          id = shift(cumsum(purrr::accumulate(amount, 
                                              ~ifelse(.x < 0.2, .x + .y, .y)) > 0.2), 
                     fill = 0) + 1)][]
#>       amount     csum id
#>  1: 0.009288 0.009288  1
#>  2: 0.189386 0.198674  1
#>  3: 0.071265 0.269939  1
#>  4: 0.137387 0.407326  2
#>  5: 0.032742 0.440068  2
#>  6: 0.000003 0.440071  2
#>  7: 0.071265 0.511336  2
#>  8: 0.122247 0.633583  3
#>  9: 0.124920 0.758503  3
#> 10: 0.032743 0.791246  4

相关问题