说我的数据看起来像这样:
level start end
1 1 133.631 825.141
2 2 133.631 155.953
3 3 146.844 155.953
4 2 293.754 302.196
5 3 293.754 302.196
6 4 293.754 301.428
7 2 326.253 343.436
8 3 326.253 343.436
9 4 333.827 343.436
10 2 578.066 611.766
11 3 578.066 611.766
12 4 578.066 587.876
13 4 598.052 611.766
14 2 811.228 825.141
15 3 811.228 825.141
或者这个:
level start end
1 1 3.60353 1112.62000
2 2 3.60353 20.35330
3 3 3.60353 8.77526
4 2 72.03720 143.60700
5 3 73.50530 101.13200
6 4 73.50530 81.64660
7 4 92.19030 101.13200
8 3 121.28500 143.60700
9 4 121.28500 128.25900
10 2 167.19700 185.04800
11 3 167.19700 183.44600
12 4 167.19700 182.84600
13 2 398.12300 418.64300
14 3 398.12300 418.64300
15 2 445.83600 454.54500
16 2 776.59400 798.34800
17 3 776.59400 796.64700
18 4 776.59400 795.91300
19 2 906.68800 915.89700
20 3 906.68800 915.89700
21 2 1099.44000 1112.62000
22 3 1099.44000 1112.62000
23 4 1100.14000 1112.62000
他们制作了以下图表:
正如您所看到的,在不同级别有几个时间间隔。 1级间隔始终跨越感兴趣的整个持续时间。级别2+的时间间隔更短。
我想要做的是选择涵盖每个时段的非重叠时间间隔的最大数量,其中包含其中的最大总时间。我用粉红色标记了那些那些。
对于小型数据帧,可以强行使用它,但显然应该有更合理的方法来实现这一点。我有兴趣听听有关我应该尝试的一些想法。
编辑:
我认为有一件事可以帮到这里,就是专栏'。结果来自Kleinberg的突发检测算法(包'突发')。您将注意到级别是按层次结构组织的。相同数量的级别不能重叠。然而,水平连续增加,例如连续行中的2,3,4可以重叠。
从本质上讲,我认为问题可以缩短到这一点。获取生成的级别,但删除级别1.这将是第二个示例的向量:
2 3 2 3 4 4 3 4 2 3 4 2 3 2 2 3 4 2 3 2 3 4
然后,看看2s ......如果少于或只有一个' 3'然后那个2是最长的间隔。但是如果在连续的2个之间有两个或更多的3个,则应该计算这些3个。为每个级别迭代执行此操作。我认为应该有用......?
e.g。
vec<-df$level %>% as.vector() %>% .[-1]
vec
#[1] 2 3 2 3 4 4 3 4 2 3 4 2 3 2 2 3 4 2 3 2 3 4
max(vec) #4
vec3<-vec #need to find two or more 4's between 3s
vec3[vec3==3]<-NA
names(vec3)<-cumsum(is.na(vec3))
0 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6 7 7 8 8
2 NA 2 NA 4 4 NA 4 2 NA 4 2 NA 2 2 NA 4 2 NA 2 NA 4
vec3.res<-which(table(vec3,names(vec3))["4",]>1)
which(names(vec3)==names(vec3.res) & vec3==4) #5 6
上面将第5行和第6行(相当于原始df中的第6行和第7行)标识为具有位于3和3之间的两个四肢。也许使用这种方法的东西可能有用吗?
答案 0 :(得分:0)
好的,这是使用您的第二个数据集进行测试。在所有情况下这可能都不正确!!
library(data.table)
dat <- fread("data.csv")
dat[,use:="maybe"]
make.pass <- function(dat,low,high,the.level,use) {
check <- dat[(use!="no" & level > the.level)]
check[,contained.by.above:=(low<=start & end<=high)]
check[,consecutive.contained.by.above:=
(contained.by.above &
!is.na(shift(contained.by.above,1)) &
shift(contained.by.above,1)),by=level]
if(!any(check[,consecutive.contained.by.above])) {
#Cause a side effect where we've learned we don't care:
dat[check[(contained.by.above),rownum],use:="no"]
print(check)
return("yes")
} else {
return("no")
}
}
dat[,rownum:=.I]
dat[level==1,use:=make.pass(dat,start,end,level,use),by=rownum]
dat
dat[use=="maybe" & level==2,use:=make.pass(dat,start,end,level,use),by=rownum]
dat
dat[use=="maybe" & level==3,use:=make.pass(dat,start,end,level,use),by=rownum]
dat
#Finally correct for last level
dat[use=="maybe" & level==4,use:="yes"]
我写了这些最后的步骤,以便您可以在自己的交互式会话中查看正在发生的事情(请参阅打印以获得一个想法),但您可以删除打印并将最后的步骤压缩为类似{{1}的内容} 回复您的评论如果有任意数量的级别,您肯定会想要使用这种形式,并在最后调用lapply(1:dat[,max(level)-1], function(the.level) dat[use=="maybe" & level==the.level,use:=make.pass......])
后跟随它。
输出:
dat[use=="maybe" & level==max(level),use:="yes"]
在关闭机会这是正确的,算法大致可以描述如下:
> dat
level start end use rownum
1: 1 3.60353 1112.62000 no 1
2: 2 3.60353 20.35330 yes 2
3: 3 3.60353 8.77526 no 3
4: 2 72.03720 143.60700 no 4
5: 3 73.50530 101.13200 no 5
6: 4 73.50530 81.64660 yes 6
7: 4 92.19030 101.13200 yes 7
8: 3 121.28500 143.60700 yes 8
9: 4 121.28500 128.25900 no 9
10: 2 167.19700 185.04800 yes 10
11: 3 167.19700 183.44600 no 11
12: 4 167.19700 182.84600 no 12
13: 2 398.12300 418.64300 yes 13
14: 3 398.12300 418.64300 no 14
15: 2 445.83600 454.54500 yes 15
16: 2 776.59400 798.34800 yes 16
17: 3 776.59400 796.64700 no 17
18: 4 776.59400 795.91300 no 18
19: 2 906.68800 915.89700 yes 19
20: 3 906.68800 915.89700 no 20
21: 2 1099.44000 1112.62000 yes 21
22: 3 1099.44000 1112.62000 no 22
23: 4 1100.14000 1112.62000 no 23
level start end use rownum
),称为 X 。考虑到 X ,将数据副本集中到所有更高级别的间隔。 让我知道你对此的看法 - 这是草稿,有些方面可能不正确。