使用二进制变量创建计数器

Create Counter with Binary Variable

我正在尝试创建一个计数器变量,每当二进制变量发生变化时它都从 1 开始。

bin <- c(1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0)
df <- as.data.frame(bin)

df <- df %>%
  group_by(bin) %>%
  mutate(cntr = row_number())

我想得到以下结果:

bin  cntr
1    1
0    1
0    2
1    1
1    2
1    3
...

但我得到的是:

1    1
0    1
0    2
1    2
1    3
1    4

我明白这是为什么……我只是不知道如何获得我想要的结果。任何帮助将不胜感激。

我们需要一个 run-length-id 来将相邻的相同元素分组到一个组中。可以使用 data.table 中的 rleid 来完成,或者创建一个逻辑索引,然后进行累加和 (cumsum(bin != lag(bin, default = first(bin))))

library(data.table)
library(dplyr)
df %>% 
   group_by(grp = rleid(bin))  %>% 
   mutate(cntr = row_number()) %>%
   ungroup %>%
   select(-grp)
# A tibble: 16 x 2
#     bin  cntr
#   <dbl> <int>
# 1     1     1
# 2     0     1
# 3     0     2
# 4     1     1
# 5     1     2
# 6     1     3
# 7     1     4
#..

data.table 中,这可以更紧凑地完成,因为 := 发生

library(data.table)
setDT(df)[, cntr := rowid(rleid(bin))]
df
#    bin cntr
# 1:   1    1
# 2:   0    1
# 3:   0    2
# 4:   1    1
# 5:   1    2
# 6:   1    3
# 7:   1    4
#..

您可以通过组合 sequencerle 轻松做到这一点。不需要软件包。

data.frame(bin, cntr = sequence(rle(bin)$lengths))
#   bin cntr
#1    1    1
#2    0    1
#3    0    2
#4    1    1
#5    1    2
#6    1    3
#7    1    4
#8    1    5
#9    0    1
#10   0    2
#11   0    3
#12   0    4
#13   1    1
#14   0    1
#15   1    1
#16   0    1