Суммируйте данные, жертвуя наименьшим разрешением (создавая группы различного размера на основе суммы отстающих значений) - PullRequest
0 голосов
/ 23 января 2019

Учитывая таблицу с отдельными показателями для разных временных точек, я хотел бы суммировать таблицу на основе суммы значений в столбце measurement текущего и предыдущего временных точек.Я хотел бы сделать это для каждой группы временных точек, где сумма текущих + предыдущих measurement с ниже определенного порога.Любая строка, где measurement выше предела, не должна суммироваться.

Предостережение: если сумма двух последовательных measurement s выше порога, но следующее измерение все еще ниже, его следует добавитьк следующей строке.

Вот пример таблицы:

d <- data.frame(name = c(rep("A", 8), rep("B", 8), rep("C", 8), rep("D", 8)),
                time = c(rep(c(1:8),4)),
                measurement = c(NA, 7, 17, 18, 30, 28, 24, 21,
                                1, 2, 3, 5, 18, 15, 38, 39,
                                11, 23, 67, 94, 405, 830, 1550, 2020,
                                25, 60, 200, 300, 1100, 2200, 3000, 3500))

Я попытался ввести столбец, который можно использовать для group_by, а затем summarise, используясумма текущих measurement, lag(measurement, order_by = time) и lag(measurement, n = 2, order_by = time) и вопрос о том, превышает ли сумма пороговое значение (например, 20).Легко видеть, что это довольно статично и неуклюже.

Кроме того, при этом мой первоначальный тест привел к суммированию name == A, а все остальные - нет.

ЧтоЯ хотел бы достичь:

   name time measurement
1     A    3          24
2     A    5          48
3     A    6          28
4     A    7          24
5     A    8          21
6     B    5          29
7     B    7          53
8     B    8          39
9     C    2          34
10    C    3          67
11    C    4          94
12    C    5         405
13    C    6         830
14    C    7        1550
15    C    8        2020
16    D    1          25
17    D    2          60
18    D    3         200
19    D    4         300
20    D    5        1100
21    D    6        2200
22    D    7        3000
23    D    8        3500

1 Ответ

0 голосов
/ 23 января 2019

Сначала вам понадобится функция условной кумулятивной суммы.Основываясь на этом ответе , вы можете сделать его с помощью или , используя .Адаптированная c++ -версия:

library(Rcpp)
boundedCumsum <- cppFunction('NumericVector boundedCumsum(NumericVector x) {
  int n = x.size();
  NumericVector out(n);
  double tmp;
  out[0] = x[0];
  for(int i = 1; i < n; ++i){
     tmp = out[i-1] + x[i];
     if(tmp > 20) 
        out[i] = 0;
     else 
        out[i] = tmp;
  }
  return out;
}')

Теперь, используя , вы можете сделать:

library(data.table) # load the package
setDT(d)            # convert 'd' to a 'data.table'

d[is.na(measurement), measurement := 0
  ][, measurement := pmax(cumsum(measurement) * (shift(measurement, fill = 21) < 20), measurement)
    , by = .(name, grp = cumsum(c(TRUE, head(boundedCumsum(measurement) == 0, -1))))
    ][measurement > 20]

, что дает:

    name time measurement
 1:    A    3          24
 2:    A    5          48
 3:    A    6          28
 4:    A    7          24
 5:    A    8          21
 6:    B    5          29
 7:    B    7          53
 8:    B    8          39
 9:    C    2          34
10:    C    3          67
11:    C    4          94
12:    C    5         405
13:    C    6         830
14:    C    7        1550
15:    C    8        2020
16:    D    1          25
17:    D    2          60
18:    D    3         200
19:    D    4         300
20:    D    5        1100
21:    D    6        2200
22:    D    7        3000
23:    D    8        3500
...