【问题标题】:How to group rows by specific range and conditionally? [closed]如何按特定范围和有条件地对行进行分组? [关闭]
【发布时间】:2020-11-06 19:15:10
【问题描述】:

我有一个基因数据集,我想在其中对基因组中物理上靠近的基因变异/行进行分组。我想对每条染色体与基因组中某些点 500 +/- 距离内的基因进行分组。

我的 'spots' 数据集是变体需要在 500 +/- 范围内的位置,并且看起来像:

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

我的lowhigh 列是我想查看下一个数据集中是否有任何行落入的范围,同时还考虑到染色体也必须匹配。

我的其他数据集有一个 position 值,我正在查看它是否符合上述任何范围并匹配 chrom

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

我尝试使用 group_by()between() 来设置范围,但我正在努力考虑需要在之前的数据集之间匹配染色体 (chrom) 然后搜索范围。

输出如下:

Gene   chrom position   Group 
Gene1   1    1200          1  #position is in one of the ranges so is in a group    
Gene2   1    10000        NA
Gene3   5    500           2  #position is in one of the ranges so is in a group
Gene4   5    560           2  #position is in the same range 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

所以我正在创建一个Group 列,该列为同一染色体上同一范围内的所有行创建一个共享编号,或者如果它们的position 在第一个数据集中的任何范围内都不匹配,则为NA。理想情况下,我正在寻找 dplyr 解决方案,因为这是我通常使用的解决方案,但我的真实数据也非常大,因此任何有帮助的指导将不胜感激。

输入数据:

#df1
structure(list(chrom = c(1L, 1L, 5L), 
    min = c(1000L, 20000L, 900L), max = c(1200L, 20100L, 1000L
    ), 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, 1L, 1L), position = c(1200L, 10000L, 
500L, 560L, 20100L)), row.names = c(NA, -5L), class = c("data.table", 
"data.frame"))

【问题讨论】:

  • 现在没有任何意义。基因 3 和 4 中的 500 和 560 介于 500-1700 和 400-1500 之间。它们应该是唯一的,或者如果满足多个范围,您需要阐明如何选择“组”的另一个条件。到目前为止,您的问题还不清楚。
  • 谢谢,我一直试图澄清这是由于基因 3 和 4 在另一个 chrom 上,所以如果 chrom 数字不同,它们应该被考虑在一个唯一的范围内以匹配chrom 号码优先。这也是我在我的问题中坚持的主要部分,我不知道如何通过chrom 有条件地分离范围考虑

标签: r dplyr data.table


【解决方案1】:

如果可以的话,您可以在多个内核上并行运行计算...虽然我不是该主题的专家,但无论如何下面的示例应该可以尝试(主要思想是搜索一个匹配的每次迭代/运行的范围并将正匹配绑定到列表)

library(dplyr)
library(plyr)
library(parallel)

# start parallel backend with 4 cores (or how many threads you have)
cl <- parallel::makeCluster(mc <- getOption("cl.cores", 4))
# export the data to the 
parallel::clusterExport(cl=cl, varlist=c("df1", "df2"))
# export packages
parallel::clusterEvalQ(cl, {library(dplyr)})
# set the lenght to one variable (could pass in the below function also)
l <- length(df1)
# run function on cluster
res <-parallel::parLapply(cl, 1:l, function(i){
  # select 1 range to match
  dfi <- df1[i, ]
  # full join all df2 with the only one range
  dfr <- dplyr::full_join(df2, dfi) %>% 
    # Check if values are in the range and give corresponding gene and chromosome
    dplyr::mutate(GENE_COR = ifelse(position >= low & position <= high, Gene, NA),
                  CHROM_COR = ifelse(position >= low & position <= high, chrom, NA)) %>% 
    # filter ever non match
    dplyr::filter(!is.na(GENE_COR))
  # return the info to puild list in parallel
  return(dfr)
}) 
# reduce result list build in parallel of only positive matches to a tibble
plyr::ldply(res, tibble)

  chrom  min  max low high  Gene position group GENE_COR CHROM_COR
1     1 1000 1200 500 1700 Gene1     1200     1    Gene1         1
2     5  900 1000 400 1500 Gene3      500     2    Gene3         5
3     5  900 1000 400 1500 Gene4      560     2    Gene4         5

虽然并行化并不总是更好 - dplyr 解决方案在函数内部 - 只需使用整个 df2 而不是 dfi

================================================ ====================

新答案:

# Build a group identifier
df1 <- df1 %>% dplyr::group_by(chrom) %>% dplyr::mutate(GROUP = dplyr::row_number(), GROUP2 = paste0(chrom, "_", dplyr::row_number())) %>% dplyr::ungroup()


df2 %>% 
  dplyr::full_join(df1) %>% 
  dplyr::mutate(CHROM_COR = ifelse(position >= low & position <= high, chrom, NA )) %>% 
  dplyr::filter(!is.na(CHROM_COR))

    Gene chrom position   min   max   low  high GROUP GROUP2 CHROM_COR
1 Gene1     1     1200  1000  1200   500  1700     1    1_1         1
2 Gene3     5      500   900  1000   400  1500     1    5_1         5
3 Gene4     1      560  1000  1200   500  1700     1    1_1         1
4 Gene5     1    20100 20000 20100 19500 20600     2    1_2         1

【讨论】:

  • 谢谢你,这看起来即使只使用 dplyr 部分它似乎运行良好。虽然我没有得到group 列输出,但您如何在此处创建group 列?
  • 您好,您在 df2 中将 group 作为输入。如果你把它拿出来,你可以使用 df1 中的 chrom 列作为我对你的数据的理解的分组标准: df1 %>% dplyr::full_join(df2) %>% dplyr::mutate(IS = ifelse(position >= 低 & 位置
  • 我将在答案中更改我的代码,因为我以某种方式互换了 df1 和 df2。您想遍历所有范围并在每次整个基因组时都匹配,反之亦然
  • 嗯,好的,谢谢,我会试试你给的。我不小心将输出示例作为输入数据。我现在更新了 df2,我需要能够通过匹配具有相同 chrom 且与 df1 处于相同低和高范围内的行来从头开始创建 group
  • 我可以通过查看输出看到分组是成功的,但是我需要这些组有一个共享的组号标识符 - 有没有办法添加这个?很抱歉我对此感到困惑,具有生物学背景,但这看起来几乎可以满足我的所有需求
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-19
  • 2018-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多