不负相思意
而从v1.9.8(新闻项目16),采用rowid与rleiddataset[, counter := rowid(rleid(input))]计时码:set.seed(1L)library(data.table)DT <- data.table(input=sample(letters, 1e6, TRUE))DT1 <- copy(DT)bench::mark(DT[, counter := seq_len(.N), by=rleid(input)], DT1[, counter := rowid(rleid(input))])时间: expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc total_time <bch:expr> <bch:t> <bch:t> <dbl> <bch:byt> <dbl> <int> <dbl> <bch:tm>1 DT[, `:=`(counter, seq_len(.N)), by = rleid(input)] 613.8ms 613.8ms 1.63 18.8MB 8.15 1 5 614ms2 DT1[, `:=`(counter, rowid(rleid(input)))] 60.5ms 71.4ms 12.7 26.4MB 14.5 7 8 553ms现在可以在名为的data.table程序包中获得下面编写的函数的高效且更直接的版本rleid。使用它,就是:setDT(dataset)[, counter := seq_len(.N), by=rleid(input)]有关?rleid更多用法和示例,请参见。感谢@Henrik提出的更新此帖子的建议。rle绝对是最方便的方法(+1 @Ananda)。但是,在更大的数据上,可以做得更好(就速度而言)。您可以按以下方式使用duplist和vecseq函数(未导出)data.table:require(data.table)arun <- function(y) { w = data.table:::duplist(list(y)) w = c(diff(w), length(y)-tail(w,1L)+1L) data.table:::vecseq(rep(1L, length(w)), w, length(y))}x <- c("a","b","b","a","a","c","a","a","a","a","b","c")arun(x)# [1] 1 1 2 1 2 1 1 2 3 4 1 1大数据基准测试:set.seed(1)x <- sample(letters, 1e6, TRUE)# rle solutionananda <- function(y) { sequence(rle(y)$lengths)}require(microbenchmark)microbenchmark(a1 <- arun(x), a2<-ananda(x), times=100)Unit: milliseconds expr min lq median uq max neval a1 <- arun(x) 123.2827 132.6777 163.3844 185.439 563.5825 100 a2 <- ananda(x) 1382.1752 1899.2517 2066.4185 2247.233 3764.0040 100identical(a1, a2) # [1] TRUE