2014-02-07 2 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) извлечь из интервалов fileA, которые перекрываются с fileB и (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 

Я не пишу часть для вывода метки еще потому, что я мог бы также исправить это первым, но я не могу понять, что я получаю г неправильно ...

[EDIT] Я также попытался следующие, но он просто выводит полноту 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

Смежные вопросы