将组ID分配给R中的数字序列

时间:2018-02-14 17:18:39

标签: r

我正在尝试按序列对测量进行分组,填写runNumber列,如下所示。每次timetep重新启动时,都必须为该序列分配一个新的runNumber。 示例数据:

    timestep robotid  runNumber 
1        0       1        1
2        0       2        1
3        1       1        1
4        2       2        1
5        0       1        2
6        1       1        2
7        1       2        2

第一次尝试适用于小型数据集,但实际数据需要很长时间。

mydata$runNumber <- 1
runcounter <- 1 

for(counter in 2:nrow(mydata)){
  if(mydata[counter-1, c("timestep")] > mydata[counter, c("timestep")]){
    runcounter <- runcounter + 1
  }
  mydata[counter, c("runNumber")] <- runcounter
}

有没有更有效的方法来实现这一目标?提前致谢。

2 个答案:

答案 0 :(得分:4)

数据:

df1 <- read.table(text = '    timestep robotid  runNumber 
1        0       1        1
                  2        1       1        1
                  3        2       2        1
                  4        0       1        2
                  5        1       1        2', header = TRUE)

df1$runNumber <- NULL  # remove runNumber column

<强>代码:

如果时间步重新开始由值0指示,那么我们可以检查它,然后从中获取逻辑向量的累积和。

within(df1, runNumber <- cumsum(timestep == 0))
#   timestep robotid runNumber
# 1        0       1          1
# 2        1       1          1
# 3        2       2          1
# 4        0       1          2
# 5        1       1          2

使用data.table会更快。试试这个:

library('data.table')
setDT(df1)[, runNumber := cumsum(timestep == 0)]
df1

编辑:根据问题中发布的新数据

数据:

df1 <- read.table(text='timestep robotid  runNumber 
                  1        0       1        1
                  2        0       2        1
                  3        1       1        1
                  4        2       2        1
                  5        0       1        2
                  6        1       1        2
                  7        1       2        2')
df1$runNumber <- NULL

<强>代码:

library('data.table')
setDT(df1)[, runNumber := {
  x <- rle(timestep == 0)  # find run length for values = 0
  y <- cumsum(x$lengths)[!x$values]   # extract the indices
  rep(seq_len(length(y)), c( y[1], diff(y)))  # create group ids
} ]

df1
#    timestep robotid runNumber
# 1:        0       1         1
# 2:        0       2         1
# 3:        1       1         1
# 4:        2       2         1
# 5:        0       1         2
# 6:        1       1         2
# 7:        1       2         2

答案 1 :(得分:0)

tidyr包具有方便的fill功能。假设每次重启时间步长== 0。

df<-read.table(header=TRUE, text="timestep robotid 
0       1
1       1
2       2
0       1
1       1")

#find the number of starts
nstarts<-length(df$timestep[df$timestep==0])
#set each restart to the sequence
df$runNumber[df$timestep==0]<-1:nstarts

#fill the rows
library(tidyr)
fill(df, runNumber)