R如何通过测量与给定值的下一个不间断序列的距离来生成降序序列

R how to generate a descending sequence by subject measuring the distance from the next uninterrupted series of a given value

我花了很多时间试图弄清楚如何创建一个特定于主题的降序序列,并测量与另一列中给定值的下一个不间断序列的距离。你有什么建议吗?

这里是问题的一个例子:

给定以下数据,其中 "id" 列是主题唯一标识符,"dummy" 列是属性

mydata<-data.frame(id=rep(seq(1,3),each=5), dummy=c(0,0,0,1,1,0,0,1,0,1,0,0,0,0,0)) 

    id dummy
1   1     0
2   1     0
3   1     0
4   1     1
5   1     1
6   2     0
7   2     0
8   2     1
9   2     0
10  2     1
11  3     0
12  3     0
13  3     0
14  3     0
15  3     0

生成一个新列,测量与 "dummy" 列中值 1 的下一个不间断系列的距离(注意:我正在考虑将值 1 的单个出现视为中断系列)。这是输出示例:

    id dummy output
1   1     0      3
2   1     0      2
3   1     0      1
4   1     1      0
5   1     1      0
6   2     0      2
7   2     0      1
8   2     1      0
9   2     0      1
10  2     1      0
11  3     0      0
12  3     0      0
13  3     0      0
14  3     0      0
15  3     0      0

谢谢, H

这是分两步使用 data.table 包的尝试。

第一步是将 dummy 列进一步移动一步,以便随后检查零序列是否跟一个。

第二步是根据它们是零序列且后跟一个序列的条件来计算序列。

我正在使用最新 data.table 版本 (v 1.9.6+) 中的 shift 函数来完成此任务,但您可以只使用 indx := c(dummy[-1L], 0L) 而不是

library(data.table) # V1.9.6+
setDT(mydata)[, indx := shift(dummy, type = "lead", fill = 0L)]
mydata[, output := .N:1L*(dummy == 0L)*(indx[.N] == 1L), by = .(id, cumsum(dummy == 1L))]
#     id dummy indx output
#  1:  1     0    0      3
#  2:  1     0    0      2
#  3:  1     0    1      1
#  4:  1     1    1      0
#  5:  1     1    0      0
#  6:  2     0    0      2
#  7:  2     0    1      1
#  8:  2     1    0      0
#  9:  2     0    1      1
# 10:  2     1    0      0
# 11:  3     0    0      0
# 12:  3     0    0      0
# 13:  3     0    0      0
# 14:  3     0    0      0
# 15:  3     0    0      0

这里有一个基数为R的选项。首先我们在dummy列中以相反的顺序标记连续相同条目(rle)的数量:

mydata$output<- unlist(sapply(rle(mydata$dummy)$lengths,function(x) rev(seq(x))))

然后我们将 dummy 不等于零的所有行的输出列的值设置为零:

mydata$output[mydata$dummy!=0] <- 0

在最后一步中,我们确定 id 的集合仅包含零作为 dummy 的值,并将它们在 output 列的条目也设置为零:

mydata[mydata$id==which(aggregate(dummy ~ id,mydata,sum)$dummy==0),]$output <- 0
#> mydata
#   id dummy output
#1   1     0      3
#2   1     0      2
#3   1     0      1
#4   1     1      0
#5   1     1      0
#6   2     0      2
#7   2     0      1
#8   2     1      0
#9   2     0      1
#10  2     1      0
#11  3     0      0
#12  3     0      0
#13  3     0      0
#14  3     0      0
#15  3     0      0

此解决方案假定 dummy 列中没有负值。