仅当 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
我想创建一个仅在满足条件时才增加的累积增量计数器。
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