使用在每个子组内重新启动的多个变量创建计数器

时间:2016-12-08 12:27:17

标签: r counter multivalue

我有一个包含两列(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包相同的结果。

2 个答案:

答案 0 :(得分:2)

使用data.table / rleid函数的rowid替代方案。使用rleid,您可以为连续值创建游程长度ID ,可以将其用作组。 1:.Nrowid可用于创建计数器。代码:

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