R中按组累积的总和,当组中的总和大于最大值时

时间:2020-02-05 11:36:40

标签: r cumulative-sum

下面的函数根据累积和是否达到某个最大值然后重新开始,将向量中的值分组。

cs_group <- function(x, threshold) {
  cumsum <- 0
  group <- 1
  result <- numeric()
  for (i in 1:length(x)) {
    cumsum <- cumsum + x[i]
    if (cumsum > threshold) {
      group <- group + 1
      cumsum <- x[i]
    }
    result = c(result, group)
  }
  return (result)
}

示例

示例中的最大值为10。第一组仅包含9;因为将其与下一个值相加将得出12的总和。下一组包括3、2、2(+8将导致值大于10)。

test <- c(9, 3, 2, 2, 8, 5, 4, 9, 1)
cs_group(test, 10)
[1] 1 2 2 2 3 4 4 5 5

但是,我更喜欢在每组中包含使累积总和大于最大值10的值。

理想的结果:

[1] 1 1 2 2 2 3 3 3 4

3 个答案:

答案 0 :(得分:5)

您可以编写自己的自定义函数或使用他人编写的代码。

I had the exact same problem几天前就已包含在MESS软件包中。

devtools::install_github("ekstroem/MESS")
MESS::cumsumbinning(test, 10, cutwhenpassed = TRUE)
#[1] 1 1 2 2 2 3 3 3 4

答案 1 :(得分:4)

一种purrr方法可能是:

cumsum(c(FALSE, diff(accumulate(test, ~ ifelse(.x >= 10, .y, .x + .y))) <= 0))

[1] 0 0 1 1 1 2 2 2 3

答案 2 :(得分:2)

出于您的目的,您的cs_group可以如下编写(如果我以正确的方式理解了背后的逻辑):

cs_group <- function(x, threshold) {
  group <- 1
  r <- c()
  repeat {
    if (length(x)==0) break
    cnt <- (idx <- max(which(cumsum(x) <= threshold)))+ifelse(idx==length(x),0,1)
    r <- c(r,rep(group, cnt))
    x <- x[-(1:cnt)]
    group <- group + 1
  }
  r
}

这样

test <- c(9, 3, 2, 2, 8, 5, 4, 9, 1)
> cs_group(test, 10)
[1] 1 1 2 2 2 3 3 3 4