Подтвердить что ты не робот

Поиск перекрытия в диапазонах с R

У меня есть два data.frames, каждый из которых содержит три столбца: chrom, start и stop, пусть называет их диапазонами A и диапазонамиB. Для каждой строки диапазонов A я ищу, чтобы найти, какая строка (если есть) в диапазонах B полностью содержит строку rangeA, под которой я подразумеваю rangesAChrom == rangesBChrom, rangesAStart >= rangesBStart and rangesAStop <= rangesBStop.

Сейчас я делаю следующее, что мне очень не нравится. Обратите внимание, что я зацикливаюсь на рядах диапазонов A по другим причинам, но ни одна из этих причин, скорее всего, не будет большой проблемой, а просто заканчивает тем, что делает вещи более читаемыми с учетом этого конкретного решения.

rangesA:

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

rangesB:

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

для каждой строки в диапазонах A:

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

Я полагаю, что лучше быть лучше (и, лучше, я имею в виду более быстрое использование больших экземпляров rangeA и диапазонов), чтобы сделать это, чем перебирать эту конструкцию. Любые идеи?

4b9b3361

Ответ 1

Это будет намного проще/быстрее, если вы можете сначала объединить два объекта.

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

Ответ 2

Используйте пакеты IRanges/GenomicRanges от Bioconductor, которые предназначены для решения этих точных проблем (и масштабируются в массовом порядке)

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

Ответ 3

Пакет 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() сортирует таблицу данных по предоставленным столбцам (в этом случае все столбцы, поскольку мы не предоставляли их), и маркирует эти столбцы как отсортированные, которые мы будем использовать позже для выполнения объединения на.

  • foverlaps() эффективно перекрывает перекрывающееся соединение. См. этот ответ для подробного объяснения и сравнения с другими подходами.

Ответ 4

Для данных примера:

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, так что каждый столбец будет одной строкой в ​​диапазонах A, а каждая строка будет соответствующей строкой в ​​диапазонах B:

> 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

Ответ 5

RangesA и RangesB являются явно синтаксисом BED, это можно сделать вне R в командной строке с помощью BEDtools, чрезвычайно быстро и гибко с помощью еще дюжины других опций для работы с геномными интервалами. Затем снова верните результаты в R.

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

Ответ 6

Я добавляю решение 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