2014-02-07 100 views
2

fileA包含區間(開始,結束),以及分配給該時間間隔(值)的值。的R - 輸出重疊的間隔

start  end  value 
0   123  1  #value 1 at positions 0 to 122 included. 
123  78000 0  #value 0 at positions 123 to 77999 included. 
78000  78004 56  #value 56 at positions 78000, 78001, 78002 and 78003. 
78004  78005 12  #value 12 at position 78004. 
78005  78006 1  #value 1 at position 78005. 
78006  78008 21  #value 21 at positions 78006 and 78007. 
78008  78056 8  #value 8 at positions 78008 to 78055 included. 
78056  81000 0  #value 0 at positions 78056 to 80999 included. 

fileB包含我感興趣的間隔的列表。我想從fileA檢索重疊的間隔。開始和結束不一定匹配。下面是fileB一個例子:

start  end  label 
77998  78005 romeo 
78007  78012 juliet 

的目標是(1)從fileAfileB和(2)連接到相應的標籤從fileB追加重疊檢索間隔。預期的結果是(#指定被丟棄的線,這是爲了幫助實現可視化,並不會在最終輸出):

start  end  value label 
# 
123  78000 0  romeo 
78000  78004 56  romeo 
78004  78005 12  romeo 
# 
78006  78008 21  juliet 
78008  78056 8  juliet 
# 

這是我在寫代碼的嘗試:

#read from tab-delimited text files which do not contain column names 
A<-read.table("fileA.txt",sep="\t",colClasses=c("numeric","numeric","numeric")) 
B<-read.table("fileB.txt",sep="\t",colClasses=c("numeric","numeric","character")) 

#add column names 
colnames(A)<-c("start","end","value") 
colnames(B)<-c("start","end","label") 

#output intervals in `fileA` that overlap with an interval in `fileB` 
A_overlaps<-A[((A$start <= B$start & A$end >= B$start) 
       |(A$start >= B$start & A$start <= B$end) 
       |(A$end >= B$start & A$end <= B$end)),] 

在這一點上我已經得到意想不到的結果:

> A_overlaps 
    start end value 
    #missing 
3 78000 78004 56 
5 78005 78006  1 #this line should not be here 
6 78006 78008 21 
    #missing 

我沒有寫部分輸出尚未標籤,因爲我還不如解決這個第一,但我想不出什麼,我剛開克錯...

[編輯] 我也試過以下,但它只是輸出的fileA全部:

A_overlaps <- A[(min(A$start,A$end) < max(B$start,B$end) 
       & max(A$start,A$end) > min(B$start,B$end)),] 
+0

有一個間隔包 – JeremyS

回答

1

這產生期望的輸出,但也可以是一個小難以閱讀

# function to find, if value lies in interval 
is.between <- function(x, a, b) { 
    (x - a) * (b - x) > 0 
} 

# apply to all rows in A 
> matching <- apply(A, MARGIN=1, FUN=function(x){ 
# which row fulfill following condition: 
+ which(apply(B, MARGIN=1, FUN=function(y){ 
# first value lies in interval from B or second value lies in interval from B 
+  is.between(as.numeric(x[1]), as.numeric(y[1]), as.numeric(y[2])) | is.between(as.numeric(x[2]), as.numeric(y[1]), as.numeric(y[2])) 
+  })) 
+ }) 
> 
# print the results 
> matching 
[[1]] 
integer(0) 

[[2]] 
[1] 1 

[[3]] 
[1] 1 

[[4]] 
[1] 1 

[[5]] 
integer(0) 

[[6]] 
[1] 2 

[[7]] 
[1] 2 

[[8]] 
integer(0) 

> 
# filter those, which has 0 length = no matching 
> A_overlaps <- A[unlist(lapply(matching, FUN=function(x)length(x)>0)),] 
# add label 
> A_overlaps$label <- B$label[unlist(matching)] 
> 
> A_overlaps 
    start end value label 
2 123 78000  0 romeo 
3 78000 78004 56 romeo 
4 78004 78005 12 romeo 
6 78006 78008 21 juliet 
7 78008 78056  8 juliet 
+0

wow-我不知道我明白了一切,但它的作品。謝謝! – biohazard

+0

我增加了一些解釋到應用功能 – Zbynek

+0

非常感謝!這是我第一次遇到apply()函數,似乎是有用的,會考慮它。 :) – biohazard