【问题标题】:How to filter rows by column value ranges in R?如何按R中的列值范围过滤行?
【发布时间】:2021-04-22 14:08:50
【问题描述】:

我有 2 个基因数据集。一个定义每行基因组中的范围,另一个数据集是基因长度范围的行,我想确保与第一个数据集中的范围没有任何重叠。

例如,我的数据如下所示:

#df1:
Chromosome     Min      Max
1              10       500 
1              450      550
2              20       100
2              900      1500
2              200      210
3               5       15
4              10       20
#df2:
Gene   Gene.Start    Gene.End   Chromosome
Gene1   10             60           1
Gene2   950            990          1
Gene3   8              14           3

我想拉出/选择df2 中没有Gene.StartGene.End 范围的行,其中该范围内的任何内容都落在df1Min 和@987654328 中给定的范围内@ 列 - 重要的是,Chromosome 数字的考虑也必须匹配。

示例的预期输出如下所示:

Gene   Gene.Start    Gene.End   Chromosome
Gene2   950            990          1

Gene2 是唯一的基因/行,其起点和终点范围不属于与 df1 中匹配的 Chromosome(查看染色体 1 中的范围)的任何范围内。

要编写此代码,我正在尝试使用 data.table,但我不确定如何让范围被视为我想要的那样。

我一直在努力让它工作,但我不确定我在做什么:

df2[df1, match := i.Gene,
                 on = .(Chromosome, (df2$Gene.Start > & < df2$Gene.End) > Min, (df2$Gene.Start > & < df2$Gene.End) < Max)]

Error: unexpected '&'

如何根据另一个数据帧中的范围按范围过滤数据帧?

输入数据示例:

df1 <- structure(list(Chromosome = c(1L, 1L, 2L, 2L, 2L, 3L, 4L), Min = c(10L, 
450L, 20L, 900L, 200L, 5L, 10L), Max = c(500L, 550L, 100L, 1500L, 
210L, 15L, 20L)), row.names = c(NA, -7L), class = c("data.table", 
"data.frame"))
df2 <- structure(list(Gene = c("Gene1", "Gene2", "Gene3"), Gene.Start = c(10L, 
950L, 8L), Gene.End = c(60L, 990L, 14L), Chromosome = c(1L, 1L, 
3L)), row.names = c(NA, -3L), class = c("data.table", "data.frame"
))

【问题讨论】:

  • 不是 R,但 bedtools 就是为此而设计的。在 R 中,您可以尝试 GenomicRanges,或者在 data.table 中,特别是 foverlaps() 函数。

标签: r data.table bioinformatics overlap


【解决方案1】:

这是data.table 方法

library(data.table)
# keep Gene that are not joined in the non-equi join on df1 below
df2[!Gene %in% df2[df1, on = .(Chromosome, Gene.Start >= Min, Gene.End <= Max)]$Gene, ]
#     Gene Gene.Start Gene.End Chromosome
# 1: Gene2        950      990          1

【讨论】:

    【解决方案2】:

    这是我对dplyr 方法的尝试。请告诉我。

    library(dplyr)
    library(tidyr)
    df2 %>% 
      right_join(df1, by = "Chromosome") %>% 
      filter(Gene.Start<Min | Gene.Start>Max, Gene.End>Max | Gene.End>Min) %>% 
      distinct(Gene, Gene.Start, Gene.End, Chromosome, .keep_all = TRUE) %>% 
      select(Gene, Gene.Start, Gene.End, Chromosome)
    

    输出:

       Gene Gene.Start Gene.End Chromosome
    1 Gene2        950      990          1
    

    【讨论】:

      【解决方案3】:

      data.table 解决方案效果最好,因为它在我更大的真实数据上是最快的,但我最终找到了 GenomicRanges 的另一个解决方案,所以我想我也会分享给其他人以供将来参考:

      library(GenomicRanges)
      
      gr1 <- makeGRangesFromDataFrame(
        data.frame(
          chr=df1$Chromosome,
          start=df1$Min,
          end=df1$Max),
        keep.extra.columns=TRUE)
      
      gr2 <- makeGRangesFromDataFrame(
        data.frame(
          chr=df2$Chromosome,
          start=df2$Gene.Start,
          end=df2$Gene.End,
          Gene = df2$Gene),
        keep.extra.columns=TRUE)
      
      no_overlaps <- gr2[-queryHits(findOverlaps(gr2, gr1, type="any")),] 
      
      no_overlap_genes <- unique(no_overlaps$Gene)
      
      gene_matches <- df2[Gene %in% no_overlap_genes]
      

      【讨论】:

        猜你喜欢
        • 2021-01-07
        • 2022-01-14
        • 1970-01-01
        • 2020-08-24
        • 1970-01-01
        • 1970-01-01
        • 2020-01-20
        • 2016-12-23
        • 2023-03-17
        相关资源
        最近更新 更多