2016-01-22 31 views
2

经过大量的思考和谷歌搜索后,我找不到解决我的问题,我希望你能帮助我。R找到时间段之间的重叠

我有一个ID列可以重复2次以上的大数据框,一个开始和结束日期列将构成一个时间段。我想知道,按照ID进行分组,如果该ID的任何时间段与另一个ID重叠,并且如果是,则通过例如创建新列来标记该ID,说明该ID是否具有重叠。

下面是一个例子的数据帧已经具有期望的新列:

structure(list(ID= c(34L, 34L, 80L, 80L, 81L, 81L, 81L, 94L, 
94L), Start = structure(c(1072911600, 1262300400, 1157061600, 
1277935200, 1157061600, 1277935200, 1157061600, 1075590000, 1285891200 
), class = c("POSIXct", "POSIXt"), tzone = ""), End = structure(c(1262214000, 
1409436000, 1251669600, 1404079200, 1251669600, 1404079200, 1251669600, 
1264892400, 1475193600), class = c("POSIXct", "POSIXt"), tzone = ""), 
    Overlap = c(FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, 
    FALSE, FALSE)), .Names = c("ID", "Start", "End", "Overlap" 
), row.names = c(NA, -9L), class = "data.frame") 


ID    Start     End Overlap 
34 2004-01-01 00:00:00 2009-12-31 00:00:00 FALSE 
34 2010-01-01 00:00:00 2014-08-31 00:00:00 FALSE 
80 2006-09-01 00:00:00 2009-08-31 00:00:00 FALSE 
80 2010-07-01 00:00:00 2014-06-30 00:00:00 FALSE 
81 2006-09-01 00:00:00 2009-08-31 00:00:00 TRUE 
81 2010-07-01 00:00:00 2014-06-30 00:00:00 TRUE 
81 2006-09-01 00:00:00 2009-08-31 00:00:00 TRUE 
94 2004-02-01 00:00:00 2010-01-31 00:00:00 FALSE 
94 2010-10-01 02:00:00 2016-09-30 02:00:00 FALSE 

在这种情况下,对于ID“81”有两个时间周期之间的重叠,所以我想标志的所有行ID = 81为TRUE,这意味着在该ID的至少两行中发现重叠。这只是一个理想的解决方案,但总的来说,我想要做的就是根据ID进行分组时找出重叠部分,因此标记它的方式可以灵活,以便简化事情。

在此先感谢您的帮助。

+0

有什么你已经试过了?你卡在哪里? –

+0

从data.table包中检查'foverlaps'。 [这是一个让你开始的帖子](http://stackoverflow.com/questions/24480031/roll-join-with-start-end-window/25655497#25655497)。 – Arun

回答

0

我认为这是你正在寻找的代码?让我知道。

data<- structure(list(ID= c(34L, 34L, 80L, 80L, 81L, 81L, 81L, 94L, 
          94L), Start = structure(c(1072911600, 1262300400, 1157061600, 
                 1277935200, 1157061600, 1277935200, 1157061600, 1075590000, 1285891200 
          ), class = c("POSIXct", "POSIXt"), tzone = ""), End = structure(c(1262214000, 
                           1409436000, 1251669600, 1404079200, 1251669600, 1404079200, 1251669600, 
                           1264892400, 1475193600), class = c("POSIXct", "POSIXt"), tzone = ""), 
         Overlap = c(FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, 
            FALSE, FALSE)), .Names = c("ID", "Start", "End", "Overlap" 
           ), row.names = c(NA, -9L), class = "data.frame") 

library("dplyr") 
library("lubridate") 

overlaps<- function(intervals){ 
     for(i in 1:(length(intervals)-1)){ 
       for(j in (i+1):length(intervals)){ 
         if(int_overlaps(intervals[i],intervals[j])){ 
           return(TRUE) 
         } 
       } 
     } 
     return(FALSE) 
} 

data %>% 
     mutate(Interval=interval(Start,End))%>% 
     group_by(ID) %>% 
     do({ 
       df<-. 
       ovl<- overlaps(df$Interval) 
       return(data.frame(ID=df$ID[1], ovl)) 
     }) 

而且,我希望有人想出了一个更好的解决方案,以我的overlaps功能..

+0

谢谢,这工作完美。 由于某些原因,lukeA的解决方案无法正常工作,即使它看起来像一个更简单的解决方案 – RabidHealer

3

另一种选择 - 假设df包含您的数据帧,则:

library(data.table) 
dt <- data.table(df, key=c("Start", "End"))[, `:=`(Overlap=NULL, row=1:nrow(df))] 
overlapping <- unique(foverlaps(dt, dt)[ID==i.ID & row!=i.row, ID]) 
dt[, `:=`(Overlap=FALSE, row=NULL)][ID %in% overlapping, Overlap:=TRUE][order(ID, Start)] 
# ID    Start     End Overlap 
# 1: 34 2004-01-01 00:00:00 2009-12-31 00:00:00 FALSE 
# 2: 34 2010-01-01 00:00:00 2014-08-31 00:00:00 FALSE 
# 3: 80 2006-09-01 00:00:00 2009-08-31 00:00:00 FALSE 
# 4: 80 2010-07-01 00:00:00 2014-06-30 00:00:00 FALSE 
# 5: 81 2006-09-01 00:00:00 2009-08-31 00:00:00 TRUE 
# 6: 81 2006-09-01 00:00:00 2009-08-31 00:00:00 TRUE 
# 7: 81 2010-07-01 00:00:00 2014-06-30 00:00:00 TRUE 
# 8: 94 2004-02-01 00:00:00 2010-01-31 00:00:00 FALSE 
# 9: 94 2010-10-01 02:00:00 2016-09-30 02:00:00 FALSE 
+0

您是否有类似的解决方案使用'dplyr'等价包? –

+1

没有抱歉,afaik在dplyr中没有'foverlaps'吊坠。 – lukeA

+0

我正在尝试使用您的解决方案来处理一个非常相似的情况,只是我不需要为给定的'ID'标记所有行,而只需要标记具有重叠的行。对于这个特殊的例子,只有行为:“TRUE”:5,6而不是7。**是否有任何快速修改您的答案获取此?**在这[后](http://stackoverflow.com/questions/325933 /确定是否两个日期范围重叠)这是一个很好的关于日期重叠的讨论,他们提出这个公式的条件:max(startA,startB)<= min(endA,endB)'。我不知道它是否会比'foverlaps'更好。任何想法 –