使用在每个子组内重新启动的多个变量创建计数器
Create counter with multiple variables that restart within each subgroup
我有一个包含两列(标识和值)的数据框。我想创建一个计数器,每次 ident 值更改时以及每个 ident 中的值更改时都会重新启动。下面举个例子来说明一下。
# 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 包相同的结果。
我们可以paste
这两个值放在一起,利用rle
的length
属性来得到连续数的长度。然后我们使用 sequence
来生成计数器。
df$counter <- sequence(rle(paste0(df$dent, df$value))$lengths)
df
# dent 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
A 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))
我有一个包含两列(标识和值)的数据框。我想创建一个计数器,每次 ident 值更改时以及每个 ident 中的值更改时都会重新启动。下面举个例子来说明一下。
# 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 包相同的结果。
我们可以paste
这两个值放在一起,利用rle
的length
属性来得到连续数的长度。然后我们使用 sequence
来生成计数器。
df$counter <- sequence(rle(paste0(df$dent, df$value))$lengths)
df
# dent 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
A 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))