Use avewith seq_along:
> mydf$C <- with(mydf, ave(A, A, B, FUN = seq_along))
> mydf
A B C
1 1 1 1
2 1 2 1
3 1 2 2
4 1 3 1
5 1 3 2
6 1 3 3
7 1 4 1
8 1 4 2
If your data is already ordered (as in this case), you can also use sequencewith rle( mydf$C <- sequence(rle(do.call(paste, mydf))$lengths)), but you do not have this restriction with ave.
If you are a fan data.table, you can use .Nas follows:
library(data.table)
DT <- data.table(mydf)
DT[, C := sequence(.N), by = c("A", "B")]
DT
source
share