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
列中没有负值。
我花了很多时间试图弄清楚如何创建一个特定于主题的降序序列,并测量与另一列中给定值的下一个不间断序列的距离。你有什么建议吗?
这里是问题的一个例子:
给定以下数据,其中 "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
列中没有负值。