读取带有标签的BAM到tbl / recursive dplyr :: bind_cols列表列表

时间:2017-06-20 11:47:53

标签: r dplyr bioinformatics bioconductor purrr

我想在包含一些标签的BAM文件中阅读,然后将其转换为pip install pycomm以进行进一步处理。

一般来说,这可以很简单地实现:

tibble

library(Rsamtools) library(tidyverse) map.info <- c("rname", "strand", "pos") map.params <- ScanBamParam(what = map.info) bam <- scanBam(bam.file, param = map.params) 会返回一个包含命名向量scanBamrnamestrand的列表,可以使用pos轻松加入。但是,假设我对dplyr::bind_cols(bam) - 标签感兴趣,我需要执行以下操作:

MD

现在,map.params <- ScanBamParam(what = map.info, tag = c("MD")) bam <- scanBam(bam.file, param = map.params) 是一个列表列表,其中包含命名向量bamrnamestrand,但另一个pos本身也是如此一个列表,其中一个名为vector tag

MD无法处理此嵌套列表列表,并引发错误,但dplyr::bind_cols有效。

TL; DR

一个充满了问题的玩具示例:

as.data.frame(bam)

有没有办法在嵌套列表中递归> df.list <- list(a = 1:2, b = 3:4, c = 5:6) > df.nest <- list(a = 1:2, b = 3:4, c = 5:6, d = list( e = 7:8 )) > dplyr::bind_cols(df.list) # A tibble: 2 x 3 a b c <int> <int> <int> 1 1 3 5 2 2 4 6 > dplyr::bind_cols(df.nest) Error in cbind_all(x) : Argument 4 must be length 2, not 1 > as.data.frame(df.nest) a b c e 1 1 3 5 7 2 2 4 6 8

暂定答案

受到@ mt1022答案的启发,并且没有进一步检查bind_cols基本代码,似乎尽管格式与玩具示例非常相似,但Rsamtools输出的行为并不像玩具示例。

但是,正如我们所知道的那样,以下内容也应该实现完全合并scanBam

tibble

它似乎比我希望的(或预期的)更加晦涩,但它确实有效。

基准

有三个选项可以产生类似的结果:

  1. map.info <- c("rname", "strand", "pos") map.params <- ScanBamParam(what = map.info, tag = c("MD", "NM")) bam <- scanBam(bam.file, param = map.params) bam.tbl <- bind_cols(do.call(bind_cols, bam[[1]][c("rname", "strand", "pos")]), do.call(bind_cols, bam[[1]]$tag))
  2. as.data.frame(bam)
  3. bind_cols(do.call(bind_cols, bam[[1]][map.info]), do.call(bind_cols, bam[[1]]$tag))
  4. 我认为一个带有bind_cols(lapply(bam, as.data.frame), .id = 'rn')行的示例bam文件应该可以很好地了解哪种方法最快。

    10762160

    as&#39; clunky&#39;看起来,我想对> length(bam[[1]]$rname) [1] 10762160 > system.time(for (i in 1:100) as.data.frame(bam)) user system elapsed 70.565 25.821 96.699 > system.time(for (i in 1:100) bind_cols(do.call(bind_cols, bam[[1]][mapI]), do.call(bind_cols, bam[[1]]$tag))) user system elapsed 0.124 0.020 0.144 > system.time(for (i in 1:100) dplyr::bind_rows(lapply(bam, as.data.frame), .id = 'rn')) user system elapsed 108.091 36.046 144.623 的嵌套调用是最快的!

1 个答案:

答案 0 :(得分:0)

bind_cols手册中的这个例子的启发:

# You can mix vectors and data frames:
bind_rows(
  c(a = 1, b = 2),
  data_frame(a = 3:4, b = 5:6),
  c(a = 7, b = 8)
)

我想我们可以尝试:

do.call(bind_cols, df.nest)
# # A tibble: 2 x 4
#       a     b     c     e
#   <int> <int> <int> <int>
# 1     1     3     5     7
# 2     2     4     6     8

编辑:一个真实的例子

library(Rsamtools)
# generate sample data using internal bam file of Rsamtools
which <- RangesList(seq1=IRanges(1000, 2000),
                    seq2=IRanges(c(100, 1000), c(1000, 2000)))
what <- c("rname", "strand", "pos")
param <- ScanBamParam(which=which, what=what, tag = c("NM"))

bamFile <- system.file("extdata", "ex1.bam", package="Rsamtools")
bam <- scanBam(bamFile, param=param)

# convert bam to a data.frame
bam.df <- dplyr::bind_rows(lapply(bam, as.data.frame), .id = 'rn')

#                  rn rname strand  pos NM
# 1    seq1:1000-2000  seq1      +  970  0
# 2    seq1:1000-2000  seq1      +  971  0
# 3    seq1:1000-2000  seq1      +  972  0
# ......