Reputation: 231
I have a dataset the following
DT <- data.drame(v1 = c(0,0,0,1,0,0,1))
I want to create a ID cumulatively stopped at a value of 1.
The ID should be
ID<-c(1,2,3,4,1,2,3)
Upvotes: 0
Views: 112
Reputation: 1486
If you are using dplyr, this will do the trick.
DT = data.frame(v1 = c(0,0,0,1,0,0,1))
DT %>%
dplyr::mutate(rno = row_number()) %>%
dplyr::mutate(group = ifelse(v1 == 0, NA, rno)) %>%
tidyr::fill(group, .direction = "up") %>%
dplyr::group_by(group) %>%
dplyr::mutate(ID = row_number()) %>%
dplyr::ungroup() %>%
dplyr::select(v1, ID)
Upvotes: 1
Reputation: 388982
In base R, we can use ave
:
with(DT, ave(v1, c(0, cumsum(v1)[-length(v1)]), FUN = seq_along))
#[1] 1 2 3 4 1 2 3
In dplyr
, we can use lag
to create groups and assign row number in each group.
library(dplyr)
DT %>% group_by(gr = lag(cumsum(v1), default = 0)) %>% mutate(ID = row_number())
and we can use the same logic in data.table
:
library(data.table)
setDT(DT)[, ID := seq_len(.N), shift(cumsum(v1), fill = 0)]
Upvotes: 0