Получить конкретный диапазон, который перекрывается
У меня есть два кадра данных: cnv_1
chr start end
3 62860387 63000898
12 31296219 31406907
14 39762575 39769146
19 43372386 43519442
19 56419263 56572829
cnv_2
chr start end
6 30994163 30995078
19 43403531 44608011
18 1731154 1833682
3 46985863 47164711
с aprox 150000 записей каждый. Я хотел бы знать, какие фрагменты cnv_1
перекрываются каким-либо образом с cnv_2
и - это наиболее важно для меня - получить конкретный регион, который перекрывается. Например, сделав это с data.frames примера, чтобы получить:
chr start end
19 43403531 43519442
большое спасибо вам
2 ответа
Решение
На основании общей ссылки:
cnv_3 <- merge(cnv_1, cnv_2, by = "chr", suffixes = letters[1:2])
# below function has 3 conditions : 1 fully inside the interval and 2 partial overlap cases
func <- function(x){
if(x["starta"]>x["startb"] & x["enda"]<x["endb"])
x
else if( x["starta"]<x["startb"] & x["enda"] < x["endb"]){
x["starta"]=x["startb"]
x
} else if( x["starta"] >x["startb"]&x["starta"]<x["endb"]&x["enda"]>x["endb"]){
x["enda"]=x["endb"]
x
}
else
c(x[1] ,rep(NA, length(x)-1))
}
df <- data.frame(t(apply(cnv_3, 1, func)))
df <- df[!is.na(df[,1]),][1:3]
colnames(df) <- colnames(cnv_1)
# incase you want all the original cnv_1 rows with NA's for non-overlapping
xxx <- cnv_1[!(cnv_1$chr %in% df$chr),]
xxx$start <- xxx$end <- NA
rbind(xxx, df)
# chr start end
#2 12 NA NA
#3 14 NA NA
#31 3 NA NA
#4 19 43403531 43519442
#5 19 NA NA
Вот dplyr
Цепочка, объединяющая общие области между двумя фреймами данных, ищет перекрытия и получает начальные и конечные значения.
library(dplyr)
inner_join(cnv_1, cnv_2, by="chr") %>%
filter(!(start.x > end.y | start.y > end.x)) %>%
transmute(chr, start.o = ifelse(start.y > start.x, start.y, start.x),
end.o = ifelse(end.y > end.x, end.x, end.y))
Выход:
chr start.o end.o
1 19 43403531 43519442
Это работает симметрично для двух фреймов данных. Если вы хотите перекрытия только в одну сторону, вы можете упростить filter
а также transmute
выражения по мере необходимости.