当前位置: 首页 > 知识库问答 >
问题:

如何对范围内的行进行分组并考虑第三列?

左丘耀
2023-03-14

我有一个遗传数据集,我想对基因组中物理上接近的遗传变异/行进行分组。我想对每个染色体(染色体)基因组中某些斑点范围内的基因进行分组。

我的“spots”数据集包含变量/行需要在一定范围内的位置,如下所示:

 chrom      low       high
   1        500       1700
   1        19500     20600
   5        400       1500

我的< code>low和< code>high列是我希望查看下一个数据集中是否有任何行落入其中的范围,同时考虑到染色体(< code>chrom)也必须匹配。具有唯一范围和chrom组合的每一行都是它自己的组,我正在查看我的另一个数据集中是否有任何内容属于该组。

我的另一个数据集有一个位置值,我正在查看它是否符合上面的任何范围,匹配<code>chrom,以便将其标记为对应于该范围,然后我可以将相同范围和chrom中的位置分组在一起:

Gene   chrom position 
Gene1   1    1200          
Gene2   1    10000        
Gene3   5    500 
Gene4   5    560
Gene5   1    20100           

我曾尝试使用<code>group_by())。

输出如下所示:

Gene   chrom position   Group 
Gene1   1    1200          1  #position is in one of the ranges and matches the chrom so is in a group    
Gene2   1    10000        NA  #does not fit into any range on chrom 2 (no matches)
Gene3   5    500           2  #position is in one of the ranges and matches the chrom so is in a group
Gene4   5    560           2  #position is in the same range and chrom as above so joins that group
Gene5   1    20100         3  #position matches a chrom and range and so gets a group corresponding to that particular chrom and range
  • Gene3和Gene4不在组1中,因为它们在不同的chrom上,但它们确实匹配chrom并且在我的第一个数据集的第3行的范围内-因此它们可以在对应于该范围和chrom的组中。
  • Gene5与Gene1不在同一个组中,因为它们匹配chrom,它们在lowhigh的不同范围内,因此获取自己的组为唯一的范围。

因此,我创建了一个< code>Group列,对于同一< code>chrom上的< code>low和< code>high之间的同一范围内的所有行,如果它们的位置在第一个数据集中的任何范围和chrom中都不匹配,则为NA。

输入数据:

df1 <- 
structure(list(chrom = c(1L, 1L, 5L), 
   low = c(500L, 19500L, 400L), high = c(1700L, 20600L, 1500L
    )), row.names = c(NA, -3L), class = c("data.table", "data.frame"))

df2 <- 
structure(list(Gene = c("Gene1", "Gene2", "Gene3", "Gene4", "Gene5"
), chrom = c(1L, 1L, 5L, 5L, 1L), position = c(1200L, 10000L, 
500L, 560L, 20100L)), row.names = c(NA, -5L), class = c("data.table", 
"data.frame"))

我还在考虑为每个唯一范围和 chrom 组合为我的第一个数据集提供唯一标识符,然后将该标识符分配给数据集 2 中与该组合匹配的任何行,以便该标识符创建我的组编号列。虽然我的真实数据是2.3k行的范围和82k行以匹配到共享组中,所以我在运行我通常会尝试的dplyr选项时也遇到了问题。

共有3个答案

印劲
2023-03-14
匿名用户

正如注释中所指出的,您只需使用< code>GenomicRanges中的< code>findOverlaps来查找包含第二个data.frame中行的参考数据帧中的行

您的df2与示例中显示的有点不同,因此我将其更改为匹配:

df2 = structure(list(Gene = c("Gene1", "Gene2", "Gene3", "Gene4", "Gene5"
), chrom = c(1L, 1L, 5L, 5L, 1L), position = c(1200L, 10000L, 
500L, 560L, 20100L)), row.names = c(NA, -5L), class = c("data.table", 
"data.frame"))

你的 df1 有不同的顺序:

  chrom   min   max   low  high
1     1  1000  1200   500  1700
2     1 20000 20100 19500 20600
3     5   900  1000   400  1500

我们可以制作一个GenomicRanges对象,如下所示:

library(GenomicRanges)
gr1 = makeGRangesFromDataFrame(df1,start.field="low",end.field="high")
gr1$Group = 1:length(gr1)

        GRanges object with 3 ranges and 1 metadata column:
      seqnames      ranges strand |     Group
         <Rle>   <IRanges>  <Rle> | <integer>
  [1]        1    500-1700      * |         1
  [2]        1 19500-20600      * |         2
  [3]        5    400-1500      * |         3

然后对第二个数据帧执行同样的操作并找到重叠:

gr2 = makeGRangesFromDataFrame(df2,start.field="position",end.field="position")
ovlp = as.data.frame(findOverlaps(gr2,gr1))
df2$Group = ovlp$subjectHits[match(1:length(gr2),ovlp$queryHits)]

  Gene chrom position Group
1 Gene1     1     1200     1
2 Gene2     1    10000    NA
3 Gene3     5      500     3
4 Gene4     1      560     1
5 Gene5     1    20100     2

闾丘成双
2023-03-14

如果您了解sql,那么可以在sql R中快速解决此问题:

df1$group_id <- seq(nrow(df1)) #This creates the unique groups for each interval

sqldf::sqldf('
    SELECT df2.*, df1.group_id 
    FROM df2 
    LEFT JOIN df1 
    ON df2.chrom = df1.chrom AND position between low AND high')

  Gene chrom position group_id
1 Gene1     1     1200        1
2 Gene2     1    10000       NA
3 Gene3     5      500        3
4 Gene4     5      560        3
5 Gene5     1    20100        2
桂德义
2023-03-14

您可以在< code>data.table中使用非对等联接:

library(data.table)
df1 <- setDT(df1)
df2 <- setDT(df2)

df1[,group := 1:.N]
df1[df2,on = .(chrom, low < position, high > position)]


   chrom   low  high group  Gene
1:     1  1200  1200     1 Gene1
2:     1 10000 10000    NA Gene2
3:     5   500   500     3 Gene3
4:     5   560   560     3 Gene4
5:     1 20100 20100     2 Gene5

在这里,我首先为df1的每一行设置一个组。合并后,如果满足条件,则该行将与组相关联。

非均衡合并不是超级直观的,而是超级强大和明确的:合并条件<code>。(色度,低

data.table中,当你这样做时

df1[df2,on = something]

您用满足上表示的条件的df2行子集df1。如果某事只是df1df2的公共变量,那么它等价于

merge(df1,df2,all.y = T,by = "someting")

但是,某些内容可以是两个 data.表中的变量之间的变量和条件的列表。此处,.() 表示列表,.(铬,低

使用不等式的非等比合并的输出替换了主数据不等式中表示的变量。表(即,df1)中的变量。表(即这里的df2),因此lowhigh成为位置。如果要保持<code>低

您实际上可以进行相反的合并,我们通过df1条目子集df2,条件相同:

df2[df1,on = .(chrom,position >low , position<high)]

    Gene chrom position position.1 group
1: Gene1     1      500       1700     1
2: Gene5     1    19500      20600     2
3: Gene3     5      400       1500     3
4: Gene4     5      400       1500     3

在这里,您将df1子集为df2的条目,这些条目满足 = .()中表示的条件,并获得实际上属于一个组的Gene列表(Gene2不在这里,因为它与子集不匹配)。

与上面解释的类似,这里<code>位置<code>变为<code>低<code>和<code>高<code>

我刚刚看到了@DavidArenburg的评论,这是我建议和解释的更简洁和更好的版本:

df2[, grp := df1[.SD, which = TRUE, on = .(chrom, low <= position, high >= position)]]

直接关联非等式合并的结果 df1[df2,on = .(铬,低

 类似资料:
  • 问题内容: 我有一个表,其中包含开始时间(在示例中使用数字以使其保持简单)以及事件的持续时间。 我想确定“块”及其开始时间和结束时间。 每当前一行的结束时间(开始时间+持续时间)(按开始时间排序)与当前行的开始时间之间的差值为时,应开始一个新的“块”。 这是我的测试数据,包括在注释中尝试进行图形解释的尝试: 第一个块开始于,结束于。由于与下一行的区别是,开始另一个块,终止于。 我可以使用来识别块的

  • 问题内容: 我有一个包含类别,日期和费率的表。每个类别在不同日期可以具有不同的费率,一个类别在给定日期只能具有一个费率。 唯一索引(类别,日期,费率)我希望针对每个类别将所有连续的日期范围归为一组,并仅保留范围的开始和结束。对于前面的示例,我们将有: 我在论坛中找到了一个类似的解决方案,但并未完全给出结果 请参见SQL FIDDLE 如何在mysql中做同样的事情?请帮忙! 问题答案: MySQL

  • 问题内容: 假设我有一个带有数字列的表(我们称其为“分数”)。 我想生成一个计数表,该表显示每个范围内得分出现的次数。 例如: 在此示例中,分数在0到9之间的行有11行,分数在10到19之间的行有14行,分数在20-29范围内的行有3行。 有一个简单的方法来设置它吗?您有什么推荐的吗? 问题答案: 在SQL Server 2000上,投票率最高的答案均不正确。也许它们使用的是其他版本。 这是它们在

  • 我有一个蜂巢表2columns.EmployeeID和工资。 数据如下所示。 我想根据薪金列创建分区。例如划分为10000到20000,20001到30000的工资范围。 我如何实现这一点。

  • 我是sql新手,我有一个postgresql数据库,它有: 表 我只需要从db|name1|name3获取3行 数据库有300000多行。 我尝试使用: 我得到了 但是如何在每个组中添加任何名称3在SQL和django orm中最好的方法是什么?

  • 问题内容: 所以,我有一张表,上面有这样的行: 每次扫描警报时(即每次触发或清除警报时)都会添加“已扫描的警报”行。任何警报都会添加带有特定Ev_Custom1的行。第一列Ev_Message包含一个计算机ID,该ID使我可以将警报与其他计算机分开。(您不喜欢任意的列名吗?)超过900条独特的警报消息。 我希望查询返回的内容是这样的: 这将是两个日期之间过滤的查询。我可以更改进入表的数据,但是有9