【问题标题】:GRanges as column in base::data.frameGRanges 作为 base::data.frame 中的列
【发布时间】:2020-04-09 17:35:59
【问题描述】:

我想将来自 Bioconductor 的 GenomicRanges::GRanges 对象作为单列存储在基础 R data.frame 中。我想将它放在基础 R data.frame 中的原因是因为我想编写一些 ggplot2 函数,这些函数专门用于底层的 data.frames。但是,我所做的任何尝试似乎都没有结果。基本上这就是我想要做的:

library(GenomicRanges)

x <- GRanges(c("chr1:100-200", "chr1:200-300"))

df <- data.frame(x = x, y = 1:2)

但该列会自动扩展,而我喜欢将其作为有效的 GRanges 对象保留在单个列中:

> df
  x.seqnames x.start x.end x.width x.strand y
1       chr1     100   200     101        * 1
2       chr1     200   300     101        * 2

当我使用 S4Vectors::DataFrame 时,它可以按我的意愿工作,除了我想要一个基本的 R data.frame 来做同样的事情:

> S4Vectors::DataFrame(x = x, y = 1:2)
DataFrame with 2 rows and 2 columns
             x         y
     <GRanges> <integer>
1 chr1:100-200         1
2 chr1:200-300         2

我也尝试了以下但没有成功:

> df <- data.frame(y = 1:2)
> df[["x"]] <- x
> df
  y                                                           x
1 1 <S4 class ‘GRanges’ [package “GenomicRanges”] with 7 slots>
2 2                                                        <NA>

警告信息: 在 format.data.frame(if (omit) x[seq_len(n0), , drop = FALSE] else x, 中: 损坏的数据框:列将被截断或用 NA 填充

df[["x"]] <- I(x)

rep(value, length.out = nrows) 中的错误: 尝试复制“S4”类型的对象

我在使用 vctrs::new_rcrd 实现 Granges 类的 S3 变体方面取得了一些小小的成功,但这似乎是一种非常迂回的方式来获得代表基因组范围的单个列。

【问题讨论】:

  • 嗨@teunbrand,我认为很可能只有 S4Vectors::DataFrame 允许这样做。也许另一种选择是即时转换回 Granges?像 df = data.frame(y=1:2); df$x = data.frame(x) ; makeGRangesFromDataFrame(df$x)
  • 是的,我也很害怕。我可以尝试通过即时将它们转换回来来解决它,但是 ggplot 中整洁的评估框架并没有真正允许这样做,而无需我重新编写一些核心 ggproto 类(如 Layer),我'宁可不做。

标签: r bioconductor genomicranges


【解决方案1】:

我找到了一种非常简单的方法来将 GR 对象转换为数据框,这样您就可以非常轻松地对 data.frame 进行操作。 Repitools 包中的 annoGR2DF 函数可以做到这一点。

> library(GenomicRanges)
> library(Repitools)
> 
> x <- GRanges(c("chr1:100-200", "chr1:200-300"))
> 
> df <- annoGR2DF(x)
> df
   chr start end width
1 chr1   100 200   101
2 chr1   200 300   101
> class(df)
[1] "data.frame"

【讨论】:

    【解决方案2】:

    一个不漂亮但实用的解决方案是使用 GenomicRanges 的访问器函数,然后转换为相关的数据向量,即数字或字符。我添加了 magrittr,但你也可以不添加它。

    library(GenomicRanges)
    library(magrittr)
    
    x <- GRanges(c("chr1:100-200", "chr1:200-300"))
    df <- data.frame(y = 1:2)
    df$chr <- seqnames(x) %>% as.character
    df$start <- start(x) %>% as.numeric
    df$end <- end(x) %>% as.numeric
    df$strand <- strand(x) %>% as.character
    df$width <- width(x) %>% as.numeric
    df
    

    【讨论】:

    • 感谢您花时间写一个答案,但这与我想要做的完全相反。我想将 GRange 保留为单个列,在基本 R data.frame 中。我已经编辑了我的问题以更清楚地说明“单列”,以防止将来出现混淆。
    • @teunbrand 哦,对不起,我误解了这个问题。稍后会删除,希望有人能找到答案,但似乎 S4Vectors::DataFrame 是唯一的解决方法。
    【解决方案3】:

    所以自从发布这个问题以来,我发现我的问题的症结似乎在于,只是 S4 对象的格式方法不能很好地与 data.frames 配合使用,并且将 Granges 作为列不一定是问题. (虽然 data.frame 的构造仍然是)。

    考虑一下原始问题的这一点:

    > df <- data.frame(y = 1:2)
    > df[["x"]] <- x
    > df
      y                                                           x
    1 1 <S4 class ‘GRanges’ [package “GenomicRanges”] with 7 slots>
    2 2   
    

    警告消息:在 format.data.frame(if (omit) x[seq_len(n0), , drop = FALSE] else x, : 损坏的数据帧:列将被截断或用 NA 填充

    如果我们为GRanges写一个简单的格式化方法,它不会抛出错误:

    library(GenomicRanges)
    
    format.GRanges <- function(x, ...) {showAsCell(x)}
    
    df <- data.frame(y = 1:3)
    
    df$x <- GRanges(c("chr1:100-200", "chr1:200-300", "chr2:100-200"))
    
    > df
      y            x
    1 1 chr1:100-200
    2 2 chr1:200-300
    3 3 chr2:100-200
    

    子集似乎也很好:

    > df[c(1,3),]
      y            x
    1 1 chr1:100-200
    3 3 chr2:100-200
    

    作为奖励,这似乎也适用于其他 S4 课程,例如:

    library(S4Vectors)
    
    format.Rle <- function(x, ...) {showAsCell(x)}
    
    x <- Rle(1:5, 5:1)
    
    df <- data.frame(y = 1:15)
    df$x <- x
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-03
      • 2021-08-03
      • 1970-01-01
      • 2020-08-29
      • 1970-01-01
      • 1970-01-01
      • 2020-05-29
      • 1970-01-01
      相关资源
      最近更新 更多