2015-10-17 56 views
10

我有一個與時間相關的事件的數據幀。通過兩列值的範圍查找數據幀中的匹配間隔

下面是一個例子:

Name  Event Order  Sequence  start_event  end_event  duration  Group 
JOHN  1    A    0    19   19   ID1 
JOHN  2    A    60    112   52   ID1 
JOHN  3    A    392    429   37   ID1 
JOHN  4    B    282    329   47   ID1 
JOHN  5    C    147    226   79   ID1 
JOHN  6    C    566    611   45   ID1 
ADAM  1    A    19    75   56   ID2 
ADAM  2    A    384    407   23   ID2 
ADAM  3    B    0    79   79   ID2 
ADAM  4    B    505    586   81   ID2 
ADAM  5    C    140    205   65   ID2 
ADAM  6    C    522    599   77   ID2 

本質上有兩種不同的基團,ID 1 & 2.對於每個這些基團中,有18種不同的名稱的。這些人中的每一個以三種不同的順序出現,A-C。然後他們在這些序列中有活動的時間段,並且我標記開始/結束事件並計算持續時間。

我想隔離每個人,並找到他們與相同和相同的組ID中的人匹配的時間間隔。

使用上面的示例數據,我想知道John和Adam在同一個序列中同時出現的時間。然後我想將John與ID1/ID2中17個名稱的其餘部分進行比較。

不需要需要匹配共享'活躍'時間的確切數量,我只是希望隔離的行是共同的。

我的舒適度正在使用dplyr,但我還無法解決這個問題。我環顧四周,看到了一些與鄰接矩陣相似的例子,但這些例子具有精確和精確的數據點。我無法用範圍/間隔計算出策略。

謝謝!

UPDATE: 這裏是理想的結果

Name  Event Order  Sequence  start_event  end_event  duration  Group 
    JOHN  3    A    392    429   37   ID1   
    JOHN  5    C    147    226   79   ID1 
    JOHN  6    C    566    611   45   ID1 
    ADAM  2    A    384    407   23   ID2 
    ADAM  5    C    140    205   65   ID2 
    ADAM  6    C    522    599   77   ID2 

我想你會隔離每個事件一行約翰的例子,標誌着開始/結束的時間框架,然後通過每一個名字和迭代事件在數據幀的其餘部分找到首先在同一序列內適合的時間點,然後對照約翰的標準開始/結束時間幀。

+0

這個包應該有所幫助:https://開頭CRAN。rstudio.com/web/packages/intervals/ – hrbrmstr

+4

從'data.table'包和/或[SO上的搜索結果]簽出'?foverlaps'(http://stackoverflow.com/search?tab=newest&q=%5br% 5d%20%5bdata.table%5d%20flalaps) – Arun

回答

4

據我所知,你想返回任何一行,其中具有特定序列號的約翰事件與具有相同序列值的任何其他人的事件重疊。要做到這一點,你可以使用拆分申請,結合通過序列分割,確定重疊的行,然後重新組合:

overlap <- function(start1, end1, start2, end2) pmin(end1, end2) > pmax(start2, start1) 
do.call(rbind, lapply(split(dat, dat$Sequence), function(x) { 
    jpos <- which(x$Name == "JOHN") 
    njpos <- which(x$Name != "JOHN") 
    over <- outer(jpos, njpos, function(a, b) { 
    overlap(x$start_event[a], x$end_event[a], x$start_event[b], x$end_event[b]) 
    }) 
    x[c(jpos[rowSums(over) > 0], njpos[colSums(over) > 0]),] 
})) 
#  Name EventOrder Sequence start_event end_event duration Group 
# A.2 JOHN   2  A   60  112  52 ID1 
# A.3 JOHN   3  A   392  429  37 ID1 
# A.7 ADAM   1  A   19  75  56 ID2 
# A.8 ADAM   2  A   384  407  23 ID2 
# C.5 JOHN   5  C   147  226  79 ID1 
# C.6 JOHN   6  C   566  611  45 ID1 
# C.11 ADAM   5  C   140  205  65 ID2 
# C.12 ADAM   6  C   522  599  77 ID2 

請注意,我的輸出包括未在問題出另外兩行 - 來自時間範圍[60,112]的John的序列A,其與時間範圍[19,75]中的亞當的序列A重疊。

這可以很容易地映射到dplyr語言:

library(dplyr) 
overlap <- function(start1, end1, start2, end2) pmin(end1, end2) > pmax(start2, start1) 
sliceRows <- function(name, start, end) { 
    jpos <- which(name == "JOHN") 
    njpos <- which(name != "JOHN") 
    over <- outer(jpos, njpos, function(a, b) overlap(start[a], end[a], start[b], end[b])) 
    c(jpos[rowSums(over) > 0], njpos[colSums(over) > 0]) 
} 
dat %>% 
    group_by(Sequence) %>% 
    slice(sliceRows(Name, start_event, end_event)) 
# Source: local data frame [8 x 7] 
# Groups: Sequence [3] 
# 
#  Name EventOrder Sequence start_event end_event duration Group 
# (fctr)  (int) (fctr)  (int)  (int) (int) (fctr) 
# 1 JOHN   2  A   60  112  52 ID1 
# 2 JOHN   3  A   392  429  37 ID1 
# 3 ADAM   1  A   19  75  56 ID2 
# 4 ADAM   2  A   384  407  23 ID2 
# 5 JOHN   5  C   147  226  79 ID1 
# 6 JOHN   6  C   566  611  45 ID1 
# 7 ADAM   5  C   140  205  65 ID2 
# 8 ADAM   6  C   522  599  77 ID2 

如果你希望能夠計算重疊的規定對用戶來說,這可以通過包裝操作到功能做到了指定要處理的對用戶:

overlap <- function(start1, end1, start2, end2) pmin(end1, end2) > pmax(start2, start1) 
pair.overlap <- function(dat, user1, user2) { 
    dat <- dat[dat$Name %in% c(user1, user2),] 
    do.call(rbind, lapply(split(dat, dat$Sequence), function(x) { 
    jpos <- which(x$Name == user1) 
    njpos <- which(x$Name == user2) 
    over <- outer(jpos, njpos, function(a, b) { 
     overlap(x$start_event[a], x$end_event[a], x$start_event[b], x$end_event[b]) 
    }) 
    x[c(jpos[rowSums(over) > 0], njpos[colSums(over) > 0]),] 
    })) 
} 

你可以使用pair.overlap(dat, "JOHN", "ADAM")拿到前面的輸出。產生重疊,每對用戶現在可以用combnapply完成:

apply(combn(unique(as.character(dat$Name)), 2), 2, function(x) pair.overlap(dat, x[1], x[2])) 
+0

'[0,19]'對於A來說又如何呢? 75] A,亞當? – Arun

+0

@Arun在'overlap'函數中使用'>',我沒有包含重疊爲0的情況。如果OP想要包括端點觸摸但間隔不重疊的情況,他們可以在'overlap'中將其更改爲'> ='。 – josliber

+0

重疊在這裏是1,而不是0.你使用閉區間'[]'是誤導。 – Arun