确定最大数量和最长时间间隔

时间:2016-03-15 15:45:08

标签: r

说我的数据看起来像这样:

   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

他们制作了以下图表:

enter image description here

正如您所看到的,在不同级别有几个时间间隔。 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之间的两个四肢。也许使用这种方法的东西可能有用吗?

1 个答案:

答案 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"]

在关闭机会这是正确的,算法大致可以描述如下:

  1. 尽可能标记所有间隔。
  2. 从给定级别开始。选择一个特定的间隔(> 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 ,将数据副本集中到所有更高级别的间隔。
  3. X 中包含的任何内容标记为“包含在 X 中”。
  4. 如果 X 中包含相同级别的连续间隔,则 X 不好b / c会浪费间隔。在这种情况下,标签 X 的“使用”变量为“否”,因此我们再也不会考虑 X 。 [注意:如果非强连续区间包含在 X 中,或者包含多个级别的区间可能会破坏 X 的可行性,然后可能需要更改此逻辑以计算包含的间隔,而不是查找连续的间隔。我根本没有考虑过这个问题,但现在发生在我身上,所以请自担风险。]
  5. 另一方面,如果 X 通过测试,那么我们已经确定它是好的。将其标记为“是”。但是重要,我们还必须将 X 中包含的任何单个区间标记为“no”,否则当我们迭代该步骤时,它会忘记它包含在一个好的内部间隔并将自身标记为“是”。这是副作用步骤。
  6. 现在,迭代,忽略我们已经确定的任何结果。
  7. 最后,最高级别的任何“可能”剩余都会自动进入。
  8. 让我知道你对此的看法 - 这是草稿,有些方面可能不正确。