在组上创建对的滚动索引

use*_*472 3 r

我需要从包含组的数据集创建(带有R)对的滚动索引.请考虑以下数据集:

times <- c(4,3,2)
V1 <- unlist(lapply(times, function(x) seq(1, x)))
df <- data.frame(group = rep(1:length(times), times = times), 
                 V1 = V1, 
                 rolling_index = c(1,1,2,2,3,3,4,5,5))

df
  group V1 rolling_index
1     1  1             1
2     1  2             1
3     1  3             2
4     1  4             2
5     2  1             3
6     2  2             3
7     2  3             4
8     3  1             5
9     3  2             5
Run Code Online (Sandbox Code Playgroud)

我的数据框包括变量组和V1.在每个组内,V1指定一个运行索引(可以从1开始,也可以不从1开始).

我想创建一个看起来像rolling_index的新索引变量.此变量将同一组中的行和连续的V1值分组,从而创建新的滚动索引.这个新索引必须是连续的组.如果组内存在不均匀的行数(例如,组2),则最后一行将获得其自己的滚动索引值.

akr*_*run 5

你可以试试

library(data.table)
setDT(df)[,  gr:=as.numeric(gl(.N, 2, .N)), group][, 
     rollindex:=cumsum(c(TRUE,abs(diff(gr))>0))][,gr:= NULL]
#    group V1 rolling_index rollindex
#1:     1  1             1         1
#2:     1  2             1         1
#3:     1  3             2         2
#4:     1  4             2         2
#5:     2  1             3         3
#6:     2  2             3         3
#7:     2  3             4         4
#8:     3  1             5         5
#9:     3  2             5         5
Run Code Online (Sandbox Code Playgroud)

或使用 base R

 indx1 <- !duplicated(df$group)
 indx2 <- with(df, ave(group, group, FUN=function(x)
                           gl(length(x), 2, length(x))))
 cumsum(c(TRUE,diff(indx2)>0)|indx1)
 #[1] 1 1 2 2 3 3 4 5 5
Run Code Online (Sandbox Code Playgroud)

更新

上述方法基于"组"列.假设您已按组显示序列列('V1'),如示例所示,滚动索引的创建更容易

 cumsum(!!df$V1 %%2)
 #[1] 1 1 2 2 3 3 4 5 5
Run Code Online (Sandbox Code Playgroud)

正如帖子中所提到的,如果'V1'列对于某些组没有从'1'开始,我们可以从'group'获取序列然后执行cumsum上面的操作

 cumsum(!!with(df, ave(seq_along(group), group, FUN=seq_along))%%2)
 #[1] 1 1 2 2 3 3 4 5 5
Run Code Online (Sandbox Code Playgroud)


Cat*_*ath 5

可能有一种更简单的方法,但你可以这样做:

rep_each <- unlist(mapply(function(q,r) {c(rep(2, q),rep(1, r))}, 
                          q=table(df$group)%/%2,
                          r=table(df$group)%%2))

df$rolling_index <- inverse.rle(x=list(lengths=rep_each, values=seq(rep_each)))

df$rolling_index 
#[1] 1 1 2 2 3 3 4 5 5
Run Code Online (Sandbox Code Playgroud)