Объединение объектов IRanges и ведение протоколов - PullRequest
0 голосов
/ 09 апреля 2019

Я начну с примера, а затем опишу логику, которую я пытаюсь использовать.

У меня есть два обычных IRanges объекта, которые охватывают один и тот же общий диапазон, но могут делать это в другом количестве диапазонов. Каждый IRanges имеет один mcol, но этот mcol отличается от IRanges.

a
#IRanges object with 1 range and 1 metadata column:
#          start       end     width | on_betalac
#      <integer> <integer> <integer> |  <logical>
#  [1]         1       167       167 |      FALSE
b
#IRanges object with 3 ranges and 1 metadata column:
#          start       end     width |  on_other
#      <integer> <integer> <integer> | <logical>
#  [1]         1       107       107 |     FALSE
#  [2]       108       112         5 |      TRUE
#  [3]       113       167        55 |     FALSE

Вы можете видеть оба этих IRanges диапазона от 1 до 167, но a имеет один диапазон, а b имеет три. Я хотел бы объединить их, чтобы получить вывод, как это:

my_great_function(a, b)
#IRanges object with 3 ranges and 2 metadata columns:
#          start       end     width | on_betalac  on_other
#      <integer> <integer> <integer> |  <logical> <logical>
#  [1]         1       107       107 |     FALSE     FALSE
#  [2]       108       112         5 |     FALSE      TRUE
#  [3]       113       167        55 |     FALSE     FALSE

Выходной сигнал подобен disjoin входных данных, но он сохраняет mcols и даже расширяет их так, чтобы выходной диапазон имел то же значение mcol, что и входной диапазон, который привел к нему. .

Ответы [ 2 ]

1 голос
/ 09 апреля 2019

Вариант 1: использование IRanges::findOverlaps

m <- findOverlaps(b, a)
c <- b[queryHits(m)]
mcols(c) <- cbind(mcols(c), mcols(a[subjectHits(m)]))
#IRanges object with 3 ranges and 2 metadata columns:
#          start       end     width |  on_other on_betacalc
#      <integer> <integer> <integer> | <logical>   <logical>
#  [1]         1       107       107 |     FALSE       FALSE
#  [2]       108       112         5 |      TRUE       FALSE
#  [3]       113       167        55 |     FALSE       FALSE

Полученный объект c является IRanges объектом с двумя столбцами метаданных.

Вариант 2: использование IRanges::mergeByOverlaps

c <- mergeByOverlaps(b, a)
c
#DataFrame with 3 rows and 4 columns
#          b  on_other         a on_betacalc
#  <IRanges> <logical> <IRanges>   <logical>
#1     1-107     FALSE     1-167       FALSE
#2   108-112      TRUE     1-167       FALSE
#3   113-167     FALSE     1-167       FALSE

Полученный выходной объект представляет собой DataFrame со столбцами IRanges и столбцами исходных метаданных в качестве дополнительных столбцов.

Вариант 3: Использование data.table::foverlaps

library(data.table)
a.dt <- as.data.table(cbind.data.frame(a, mcols(a)))[, width := NULL]
b.dt <- as.data.table(cbind.data.frame(b, mcols(b)))[, width := NULL]

setkey(b.dt, start, end)
foverlaps(a.dt, b.dt, type = "any")[, `:=`(i.start = NULL, i.end = NULL)][]
   start end on_other on_betacalc
1:     1 107    FALSE       FALSE
2:   108 112     TRUE       FALSE
3:   113 167    FALSE       FALSE

Полученный объект является data.table.

Вариант 4: использование fuzzyjoin::interval_left_join

library(fuzzyjoin)
a.df <- cbind.data.frame(a, mcols(a))
b.df <- cbind.data.frame(b, mcols(b))
interval_left_join(b.df, a.df, by = c("start", "end"))
#  start.x end.x width.x on_other start.y end.y width.y on_betacalc
#1       1   107     107    FALSE       1   167     167       FALSE
#2     108   112       5     TRUE       1   167     167       FALSE
#3     113   167      55    FALSE       1   167     167       FALSE

Полученный объект - data.frame.


Пример данных

library(IRanges)
a <- IRanges(1, 167)
mcols(a)$on_betacalc = F

b <- IRanges(c(1, 108, 113), c(107, 112, 167))
mcols(b)$on_other <- c(F, T, F)
0 голосов
/ 09 апреля 2019

Вот то, что я смог придумать.Не такой элегантный, как MauritsEvers, но может быть полезен для других.

combine_exposures <- function(...) {

  cd <- c(...)
  mc <- mcols(cd)
  dj <- disjoin(x = cd, with.revmap = TRUE)
  r <- mcols(dj)$revmap

  d <- as.data.frame(matrix(nrow = length(dj), ncol = ncol(mc)))
  names(d) <- names(mc)

  for (i in 1:length(dj)) {
    d[i,] <- sapply(X = 1:ncol(mc), FUN = function(j) { mc[r[[i]][j], j] })
  }

  mcols(dj) <- d
  return(dj)
}

здесь dput(c(e1, e2, e3, e4)) (e1, e2, e3 и e4 - некоторые примеры IRanges, которые охватывают 1 167):

new("IRanges", start = c(1L, 1L, 108L, 113L, 1L, 1L), width = c(167L, 
107L, 5L, 55L, 167L, 167L), NAMES = NULL, elementType = "ANY", 
    elementMetadata = new("DataFrame", rownames = NULL, nrows = 6L, 
        listData = list(on_betalac = c(FALSE, NA, NA, NA, NA, 
        NA), on_other = c(NA, FALSE, TRUE, FALSE, NA, NA), on_pen = c(NA, 
        NA, NA, NA, FALSE, NA), on_quin = c(NA, NA, NA, NA, NA, 
        FALSE)), elementType = "ANY", elementMetadata = NULL, 
        metadata = list()), metadata = list())
...