Using rle :
out <- transform(df, count = sequence(rle(do.call(paste, df))$lengths)) out$count[out$t == "R"] <- 0
If your data.frame has more than two of these columns, and you want to check only these two columns, just replace df with df[, 1:2] (or) df[, c("t", "id")] .
If you find do.call(paste, df) dangerous (like @flodel comments), you can replace it with:
as.character(interaction(df))
I personally do not find anything dangerous or clumsy in this setting (if you have the correct separator, which means that you know your data well). However, if you find this as such, a second solution may help you.
Update:
For those who don't like to use do.call(paste, df) or as.character(interaction(df)) (see comments between me, @flodel and @HongOoi), here is another basic solution:
idx <- which(df$t == "R") ww <- NULL if (length(idx) > 0) { ww <- c(min(idx), diff(idx), nrow(df)-max(idx)) df <- transform(df, count = ave(id, rep(seq_along(ww), ww), FUN=function(y) sequence(rle(y)$lengths))) df$count[idx] <- 0 } else { df$count <- seq_len(nrow(df)) }
source share