Суммарная сумма в R по группам и начинается заново, когда сумма значений в группе превышает максимальное значение - PullRequest
5 голосов
/ 05 февраля 2020

Функция, представленная ниже, группирует значения в векторе на основе того, достигла ли накопленная сумма определенного максимального значения, а затем начала заново.

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 ]

5 голосов
/ 05 февраля 2020

Вы можете написать свою собственную функцию или использовать код, написанный другими.

У меня была точно такая же проблема несколько дней назад, и она была включена в пакет MESS.

devtools::install_github("ekstroem/MESS")
MESS::cumsumbinning(test, 10, cutwhenpassed = TRUE)
#[1] 1 1 2 2 2 3 3 3 4
4 голосов
/ 05 февраля 2020

Один 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 голосов
/ 05 февраля 2020

Для вашей цели ваш cs_group может быть записан, как показано ниже (если я правильно понимаю логи c позади):

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...