r语言 - 为相等值的连续运行创建组号



是否有比使用循环更快的方法来创建计数器索引?对于相等值的每个连续运行,索引应该是相同的。我发现循环非常慢,特别是当数据非常大的时候。

为了说明,下面是输入和期望的输出

x <- c(2, 3, 9, 2, 4, 4, 3, 4, 4, 5, 5, 5, 1)

期望结果计数器:

c(1, 2, 3, 4, 5, 5, 6, 7, 7, 8, 8, 8, 9)

注意,连续运行具有不同的索引。例如,参见值24

的所需索引

我的低效代码是这样的:

group[1]<-1
counter<-1
for (i in 2:n){
if (x[i]==x[i-1]){
    group[i]<-counter
}else{
    counter<-counter+1
    group[1]<-counter}
}

使用data.table,具有rleid():

require(data.table) # v1.9.5+
rleid(x)
#  [1] 1 2 3 4 5 5 6 7 7 8 8 8 9

如果您有这样的数值,您可以使用diffcumsum将值的变化加起来

x <- c(2,3,9,2,4,4,3,4,4,5,5,5,1)
cumsum(c(1,diff(x)!=0))
# [1] 1 2 3 4 5 5 6 7 7 8 8 8 9

这将适用于字符值的数值:

rep(1:length(rle(x)$values), times = rle(x)$lengths)
#[1] 1 2 3 4 5 5 6 7 7 8 8 8 9

您也可以通过调用rle一次(大约快2倍)来提高效率,并且使用rep.int代替rep可以使非常稍微提高速度:

y <- rle(x)
rep.int(1:length(y$values), times = y$lengths)

以上Jota的回答可以进一步简化为,这样会更快

with(rle(x), rep(1:length(lengths), lengths))
 [1] 1 2 3 4 5 5 6 7 7 8 8 8 9

对于dplyr,您可以使用consecutive_id:

library(dplyr) #1.1.0+
consecutive_id(x)
# [1] 1 2 3 4 5 5 6 7 7 8 8 8 9

最新更新