为具有特定条件的标志创建ID序列

时间:2019-04-14 23:48:36

标签: r dplyr

我需要为特定条件创建一个id序列:flag == 1,我的问题的示例是:

library(dplyr)
set.seed(123)
a <- data.frame(id = 1:10,
                flag = rbinom(10,1,0.2))
print(a)

   id flag
1   1    0
2   2    0
3   3    0
4   4    1
5   5    1
6   6    0
7   7    0
8   8    1
9   9    0
10 10    0

我试图仅为flag == 1创建一个id变量,但可悲的是还标识了flag == 0,我的命令结果和期望结果的示例是:

a %>%
mutate(try_seq = cumsum(c(TRUE, diff(flag) != 0)))

>  id flag try_seq desire_seq
1   1    0       1      NA
2   2    0       1      NA    
3   3    0       1      NA
4   4    1       2      1
5   5    1       2      1
6   6    0       3      NA
7   7    0       3      NA
8   8    1       4      2
9   9    0       5      NA
10 10    0       5      NA
10 10    0       5      NA

3 个答案:

答案 0 :(得分:1)

这将返回您要查找的结果:

cumsum(c(a$flag[1], diff(a$flag)) > 0) * NA^!a$flag
 [1] NA NA NA  1  1 NA NA  2 NA NA

NA^a$flag技巧使用的想法是任何升到0次幂的值都是1。否则,我们使用diff检查变量的正变化。

答案 1 :(得分:0)

我们可以使用rle为每个1创建一个序列,否则将其更改为NA

library(dplyr)

a %>%
  mutate(ans_seq = ifelse(flag == 1, with(rle(flag == 1), 
                         rep(cumsum(!values), lengths)), NA))


#   id flag ans_seq
#1   1    0      NA
#2   2    0      NA
#3   3    0      NA
#4   4    1       1
#5   5    1       1
#6   6    0      NA
#7   7    0      NA
#8   8    1       2
#9   9    0      NA
#10 10    0      NA

也可以仅使用基数R编写

with(a, ifelse(flag == 1, with(rle(flag == 1), rep(cumsum(!values), lengths)), NA))
#[1] NA NA NA  1  1 NA NA  2 NA NA

答案 2 :(得分:0)

我们也可以不使用任何rle的情况下使用ifelse

library(dplyr)
na_if(inverse.rle(within.list(rle(a$flag), {
    i1 <- as.logical(values)
    values[i1] <- seq_along(values[i1])} )), 0)
#[1] NA NA NA  1  1 NA NA  2 NA NA

或使用data.table

library(data.table)
setDT(a)[, grp := rleid(flag)][flag != 0, desire_seq := .GRP , grp][, grp := NULL][]
#    id flag desire_seq
# 1:  1    0         NA
# 2:  2    0         NA
# 3:  3    0         NA
# 4:  4    1          1
# 5:  5    1          1
# 6:  6    0         NA
# 7:  7    0         NA
# 8:  8    1          2
# 9:  9    0         NA
#10: 10    0         NA