2016-01-22 30 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'更好。任何想法 –