Нахождение перекрытия в диапазонах с R - PullRequest
13 голосов
/ 12 октября 2010

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

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

rangeA:

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

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

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

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

Ответы [ 6 ]

20 голосов
/ 13 октября 2010

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

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
13 голосов
/ 12 октября 2010

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

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
12 голосов
/ 28 декабря 2014

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

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

3 голосов
/ 01 декабря 2016

Я добавляю решение 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
2 голосов
/ 17 июля 2013

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

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

2 голосов
/ 12 октября 2010

Для данных вашего примера:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...