仅当 r 中满足条件时数据帧内的增量计数器

incremental counter within dataframe only when a condition is met in r

我想创建一个仅在满足条件时才增加的累积增量计数器。

DT <- data.table(id = c(1, 1, 1, 1, 1, 1, 1, 2, 2, 2), 
               b = c(10L, 5L, 3L, 4L, 2L, 6L, 1L, 3L, 5L, 7L))

我用rleid没有得到想要的结果,因为当连续的行满足两个条件时,不会执行增量

> DT[,count := rleid(b>=5),id]
> DT
    id  b count
 1:  1 10     1
 2:  1  5     1
 3:  1  3     2
 4:  1  4     2
 5:  1  2     2
 6:  1  6     3
 7:  1  1     4
 8:  2  3     1
 9:  2  5     2
10:  2  7     2

预期的结果是

> DT
    id  b count
 1:  1 10     1
 2:  1  5     2
 3:  1  3     2
 4:  1  4     2
 5:  1  2     2
 6:  1  6     3
 7:  1  1     3
 8:  2  3     1
 9:  2  5     2
10:  2  7     3

这里有一个 cumsum 的选项。按'id'分组,得到逻辑表达式(b >= 5)的累加和。对于'id'2,第一个大于或等于5的元素在位置2(在分组位置),因此第一行将是0。为了使这个1,一个选项是将它转换到 factor 然后强制转换为整数,以便我们获得整数存储值(R 索引从 1 开始)

DT[, count := as.integer(factor(cumsum(b >= 5))), id]

-输出

DT
    id  b count
 1:  1 10     1
 2:  1  5     2
 3:  1  3     2
 4:  1  4     2
 5:  1  2     2
 6:  1  6     3
 7:  1  1     3
 8:  2  3     1
 9:  2  5     2
10:  2  7     3

另一个 data.table 选项 cumsum

> DT[, count := (v <- cumsum(b >= 5)) - v[1] + 1, id][]
    id  b count
 1:  1 10     1
 2:  1  5     2
 3:  1  3     2
 4:  1  4     2
 5:  1  2     2
 6:  1  6     3
 7:  1  1     3
 8:  2  3     1
 9:  2  5     2
10:  2  7     3

我们也可以使用 accumulate 函数来达到这个目的。以下是有关此解决方案的一些说明:

  • accumulate 将两个参数函数作为其 .f 参数,其中 .x 是前一个/累积值,.y 是值序列中的当前值向量的 b
  • 我将 count 的初始值设置为 1 因此删除了 b 的第一个值,因为我们不再需要它并通过 [=15 检查下一个值=] 如果满足条件则加一,否则保持原样。
library(dplyr)
library(purrr)

DT %>%
  group_by(id) %>%
  mutate(count = accumulate(b[-1], .init = 1,
                            ~ if(.y >= 5) {
                              .x + 1
                            } else {
                              .x
                            }))

# A tibble: 10 x 3
# Groups:   id [2]
      id     b count
   <dbl> <int> <dbl>
 1     1    10     1
 2     1     5     2
 3     1     3     2
 4     1     4     2
 5     1     2     2
 6     1     6     3
 7     1     1     3
 8     2     3     1
 9     2     5     2
10     2     7     3