我有一个包含两列(ident和value)的数据框。我想创建一个计数器,每当标识值更改时以及每个标识中的值更改时重新启动。这是一个明确的例子。
# ident value counter
#--------------------
# 1 0 1
# 1 0 2
# 1 1 1
# 1 1 2
# 1 1 3
# 1 0 1
# 1 1 1
# 1 1 2
# 2 1 1
# 2 0 1
# 2 0 2
# 2 0 3
我尝试了plyr包
ddply(mydf, .(ident, value), transform, .id = seq_along(ident))
与data.frame包相同的结果。
答案 0 :(得分:2)
使用data.table
/ rleid
函数的rowid
替代方案。使用rleid
,您可以为连续值创建游程长度ID ,可以将其用作组。 1:.N
或rowid
可用于创建计数器。代码:
library(data.table)
# option 1:
setDT(d)[, counter := 1:.N, by = .(ident,rleid(value))]
# option 2:
setDT(d)[, counter := rowid(ident, rleid(value))]
两者都给出了:
> d
ident value counter
1: 1 0 1
2: 1 0 2
3: 1 1 1
4: 1 1 2
5: 1 1 3
6: 1 0 1
7: 1 1 1
8: 1 1 2
9: 2 1 1
10: 2 0 1
11: 2 0 2
12: 2 0 3
使用dplyr
时,它有点简单:
library(dplyr)
d %>%
group_by(ident, val.gr = cumsum(value != lag(value, default = first(value)))) %>%
mutate(counter = row_number()) %>%
ungroup() %>%
select(-val.gr)
作为cumsum
功能的替代方案,您可以data.table
d <- structure(list(ident = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L),
value = c(0L, 0L, 1L, 1L, 1L, 0L, 1L, 1L, 1L, 0L, 0L, 0L)),
.Names = c("ident", "value"), class = "data.frame", row.names = c(NA, -12L))
{/ 3}}。
使用过的数据:
<Grid Margin="-2,-5,-6,0" HorizontalAlignment="Stretch" Background="{x:Bind GetColor()}">
答案 1 :(得分:1)
我们可以paste
将这两个值放在一起,并使用length
的{{1}}属性来获取连续数字的长度。然后我们使用rle
生成计数器。
sequence