用R查找范围中的重叠

用R查找范围中的重叠,r,bioinformatics,R,Bioinformatics,我有两个data.frames,每个都有三列:chrom、start和stop,我们称它们为rangesA和rangesB。对于rangesA的每一行,我希望找到rangesB中的哪一行(如果有的话)完全包含rangesA行-我的意思是rangesAChrom==rangesBChrom,RangeStart>=RangeSStart和rangesAStop,如果可以先合并两个对象,这将更容易/更快 ranges <- merge(rangesA,rangesB,by="chrom",su

我有两个data.frames,每个都有三列:chrom、start和stop,我们称它们为rangesA和rangesB。对于rangesA的每一行,我希望找到rangesB中的哪一行(如果有的话)完全包含rangesA行-我的意思是
rangesAChrom==rangesBChrom,RangeStart>=RangeSStart和rangesAStop,如果可以先合并两个对象,这将更容易/更快

ranges <- merge(rangesA,rangesB,by="chrom",suffixes=c("A","B"))
ranges[with(ranges, startB <= startA & stopB >= stopA),]
#  chrom startA stopA startB stopB
#1     1    200   250    200   265
#2     5    100   105     99   106
范围对于示例数据:

rangesA <- data.frame(
    chrom = c(5, 1, 9),
    start = c(100, 200, 275),
    stop = c(105, 250, 300)
)
rangesB <- data.frame(
    chrom = c(1, 5, 9),
    start = c(200, 99, 275),
    stop = c(265, 106, 290)
)

使用Bioconductor的IRanges/GenomicRanges软件包,该软件包专门用于处理这些精确的问题(并可大规模扩展)

对于不同染色体上的范围,有几个合适的容器,一个是RangesList

library(IRanges)
rangesA <- split(IRanges(rangesA$start, rangesA$stop), rangesA$chrom)
rangesB <- split(IRanges(rangesB$start, rangesB$stop), rangesB$chrom)
#which rangesB wholly contain at least one rangesA?
ov <- countOverlaps(rangesB, rangesA, type="within")>0
库(IRanges)

rangesArangesA和RangesB显然是BED语法,这可以在命令行中使用BEDtools在R之外完成,非常快速和灵活,有十几个其他选项可以处理基因组间隔。然后将结果再次输入R


数据。表
包有一个函数
foverlaps()
,该函数能够在v1.9.4之后的间隔范围内进行合并:

require(data.table)
setDT(rangesA)
setDT(rangesB)

setkey(rangesB)
foverlaps(rangesA, rangesB, type="within", nomatch=0L)
#    chrom start stop i.start i.stop
# 1:     5    99  106     100    105
# 2:     1   200  265     200    250
  • setDT()
    通过引用将data.frame转换为data.table

  • setkey()

  • foverlaps()
    重叠连接是否有效。有关详细说明以及与其他方法的比较,请参见


我添加了
dplyr
解决方案

library(dplyr)
inner_join(rangesA, rangesB, by="chrom") %>% 
  filter(start.y < start.x | stop.y > stop.x)

很好的伊朗人,忘了吧。我最终没有选择这个,因为它不适合我自己的情况,原因有很多,但还是很高兴知道。我的玩具示例遗漏了几个关键点(我自己的错误),这让我很难理解如何使用w/irange,merge()解决方案提供了巨大的加速。此外,虽然它的规模很大,但我们也看到很多非常小的情况,我假设S4的开销在这些情况下会减慢速度。是否还要计算部分重叠?想象一下这样一种情况,rangesA有20k行,rangesB有300k行->疯狂巨大连接->不可能放入R RAM内存。与伊朗人的解决方案更好
> sapply(rangesA$stop, '>=', rangesB$start) & sapply(rangesA$start, '<=', rangesB$stop)
      [,1]  [,2]  [,3]
[1,] FALSE  TRUE FALSE
[2,]  TRUE FALSE FALSE
[3,] FALSE FALSE  TRUE
source("http://bioconductor.org/biocLite.R")
biocLite("IRanges")
library(IRanges)
rangesA <- split(IRanges(rangesA$start, rangesA$stop), rangesA$chrom)
rangesB <- split(IRanges(rangesB$start, rangesB$stop), rangesB$chrom)
#which rangesB wholly contain at least one rangesA?
ov <- countOverlaps(rangesB, rangesA, type="within")>0
require(data.table)
setDT(rangesA)
setDT(rangesB)

setkey(rangesB)
foverlaps(rangesA, rangesB, type="within", nomatch=0L)
#    chrom start stop i.start i.stop
# 1:     5    99  106     100    105
# 2:     1   200  265     200    250
library(dplyr)
inner_join(rangesA, rangesB, by="chrom") %>% 
  filter(start.y < start.x | stop.y > stop.x)
  chrom start.x stop.x start.y stop.y
1     5     100    105      99    106
2     1     200    250     200    265