2016-01-26 29 views
2

我正在嘗試將一系列時間間隔合併成更少的同樣有意義的時間間隔。如何在R中將間隔數據合併爲更少的間隔?

考慮例如

Intervals = list(
    c(23,34), 
    c(45,48), 
    c(31,35), 
    c(7,16), 
    c(5,9), 
    c(56,57), 
    c(55,58) 
) 

由於間隔重疊,以相同的間隔可以與幾個矢量來描述間隔的此列表。繪製這些間隔進行明顯的是,4個矢量的列表就足夠了

plot(1,1,type="n",xlim=range(unlist(Intervals)),ylim=c(0.9,1.1)) 
segments(
    x0=sapply(Intervals,"[",1), 
    x1=sapply(Intervals,"[",2), 
    y0=rep(1,length(Intervals)), 
    y1=rep(1,length(Intervals)), 
    lwd=10 
    ) 

enter image description here

我怎樣才能減少我的Intervals名單進行比對劇情顯示的一個同樣的信息? (性能物質)

用於上述例子中的所希望的輸出是

Intervals = list(
    c(5,16) 
    c(23,35), 
    c(45,48), 
    c(55,58) 
) 
+0

當谷歌搜索「R倒閉重疊間隔」時,相當多的點擊。他們不是按照你想要的方式工作嗎?請向我們展示您的試驗。它表明你已經花時間去嘗試幫助你自己了,它使我們避免重申明顯的答案,並且它可以幫助你得到更具體和相關的答案。我敢打賭,這些可以更新一個很好的'data.table :: foverlaps'答案......乾杯。 – Henrik

+0

不一樣,但_possibly_在[本問答]中的一些相關部分(http://stackoverflow.com/questions/27574775/is-it-possible-to-use-the-r-data-table-funcion-foverlaps-找到交集) – Henrik

回答

2

你需要的是在IRangesreduce功能。與基礎R

In.df <- do.call(rbind, Intervals) 
library(IRanges) 

In.ir <- IRanges(In.df[, 1], In.df[,2]) 

out.ir <- reduce(In.ir) 
out.ir 
# IRanges of length 4 
#  start end width 
# [1]  5 16 12 
# [2] 23 35 13 
# [3] 45 48  4 
# [4] 55 58  4 
+0

IRanges似乎是一個非常方便的軟件包,以滿足我的需求。非常感謝! +1 –

0

一個選項:

首先,我把你的列表中data.frame

ints <- as.data.frame(do.call(rbind, Intervals)) 
names(ints) <- c('start', 'stop') 

所以它看起來像

start stop 
1 23 34 
2 45 48 
3 31 35 
4  7 16 
5  5 9 
6 56 57 
7 55 58 

現在,有兩個for循環比較與between,並擴大交叉時的時間間隔發現:

for(x in 1:nrow(ints)){ 
    for(y in 1:nrow(ints)){ 
    if(between(ints$start[x], ints$start[y], ints$stop[y])){ 
     ints$start[x] <- ints$start[y] 
     if(ints$stop[y] > ints$stop[x]){ 
     ints$stop[x] <- ints$stop[y] 
     } else { 
     ints$stop[y] <- ints$stop[x] 
     } 
    } 
    } 
} 

從而改變ints

> ints 
    start stop 
1 23 35 
2 45 48 
3 23 35 
4  5 16 
5  5 16 
6 55 58 
7 55 58 

簡化爲unique案件:

ints <- unique(ints, margin = 1) 

,並把它們爲了

ints <- ints[order(ints$start),] 

留下您與

> ints 
    start stop 
4  5 16 
1 23 35 
2 45 48 
6 55 58 

如果你想讓它回到像原來的列表,

Intervals <- lapply(1:nrow(ints), function(x)c(ints[x,1], ints[x,2])) 

(注:你當然可以用*apply代替for,布爾值,而不是between,和原來的列表做到這一點而不是data.frame,但是,這是可讀的。重寫/優化,只要你喜歡。)

+0

注意:'stop'可能是一個變量的錯誤名稱,但我有太多的改變。抱歉! – alistaire

+0

您的評論完全不清楚。 'stop'不是一個變量,它是一個列的名稱。 –

+0

來自''data.frame':「一個數據框是一個具有唯一行名的行數相同的變量列表,給定的類爲」data.frame「。」也就是說,無論如何,「停止」都是一個糟糕的名字。 – alistaire