簡體   English   中英

使用 R 查找范圍內的重疊

[英]Finding overlap in ranges with R

我有兩個 data.frames,每個都有三列:chrom、start 和 stop,我們稱它們為 rangeA 和 rangeB。 對於 rangeA 的每一行,我正在尋找 rangeB 中的哪一行(如果有的話)完全包含 rangeA 行 - 我的意思是rangesAChrom == rangesBChrom, rangesAStart >= rangesBStart and rangesAStop <= rangesBStop

現在我正在做以下事情,我只是不太喜歡。 請注意,由於其他原因,我正在遍歷 rangeA 的行,但這些原因都不是什么大問題,鑒於此特定解決方案,它最終只會使事情更具可讀性。

范圍A:

chrom   start   stop
 5       100     105
 1       200     250
 9       275     300

范圍B:

chrom    start    stop
  1       200      265
  5       99       106
  9       275      290

對於 rangeA 中的每一行:

matches <- which((rangesB[,'chrom']  == rangesA[row,'chrom']) &&
                 (rangesB[,'start'] <= rangesA[row, 'start']) &&
                 (rangesB[,'stop'] >= rangesA[row, 'stop']))

我認為必須有更好的(更好,我的意思是在 rangeA 和 rangeB 的大型實例上更快)的方法來做到這一點,而不是循環遍歷這個構造。 有任何想法嗎?

使用 Bioconductor 的 IRanges/GenomicRanges 包,它是為處理這些確切問題(並大規模擴展)而設計的

source("http://bioconductor.org/biocLite.R")
biocLite("IRanges")

對於不同染色體上的范圍,有幾個合適的容器,一個是 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

如果您可以先合並兩個對象,這將更容易/更快。

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

data.table包有一個函數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()按提供的列(在本例中為所有列,因為我們沒有提供任何列setkey()對 data.table 進行排序,並將這些列標記為已排序,稍后我們將使用它來執行連接。

  • foverlaps()有效地進行重疊連接。 有關詳細說明以及與其他方法的比較,請參閱此答案

RangesA 和 RangesB 顯然是 BED 語法,這可以在 R 之外使用 BEDtools 在命令行中完成,非常快速和靈活,有十幾個其他選項來處理基因組間隔。 然后將結果再次放回 R 中。

https://code.google.com/p/bedtools/

我添加了dplyr解決方案。

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

對於您的示例數據:

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)
)

這將使用sapply ,這樣每一列都是 rangeA 中的一行,而每一行都是 rangeB 中的對應行:

> 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM