在两个单独的列中折叠具有连续范围的行

Posted

技术标签:

【中文标题】在两个单独的列中折叠具有连续范围的行【英文标题】:Collapsing rows with consecutive ranges in two separate columns 【发布时间】:2021-12-09 11:41:55 【问题描述】:

非常感谢您对此提供的帮助。我正在尝试压缩 200,000+ 行的数据框,其中“start”列中一行的整数与“end”列中的下一个连续行完全相同。作为参考,这些是染色体碱基对位置,以及下面的示例代码:

genomic_ranges <- data.frame(sample_ID = c("A", "B", "B", "B", "C"),
                         start = c(1, 20, 30, 40, 250),
                         end =  c(5, 30, 40, 70, 400),
                         feature = c("normal", "DUP", "DUP", "DUP", "DUP"))
sample_ID start end feature
1         A     1   5  "normal"
2         B    20  30     "DUP"
3         B    30  40     "DUP"
4         B    40  70     "DUP"
5         C   250 400     "DUP"

我已经尝试过逻辑向量、布尔运算符、ifelse 语句、forloop 等,但我找不到一种方法来 1)删除显示中间范围的行,以及 2)将包含真正开始的第一行和最后一行粘贴在一起和范围的结束位置。

我尝试过的一些方法:

ifelse(cnv_catalogue_final$end == cnv_catalogue_final$start, "to_delete", "other"))
cnv_catalogue_final$end %in% cnv_catalogue_final$start
dplyr::filter(slice_min(start, x) | slice_max(end, x))

即使我使用像 (StartA &lt;= EndB) and (EndA &gt;= StartB) 这样的东西,我仍然会失去开始或结束位置。

*编辑:感谢大家的反馈!我已经用代码更新了这个问题。这些行确实具有由 sample_ID 标识的 ID。理想情况下,我希望 1 行具有 20-70 的完整范围,而不是将其切成 20-30、30-40 和 40-70 的段,分成 3 行具有相同的 sample_ID 标识符。

【问题讨论】:

您可能想要标记您正在使用的语言。 请与dput()分享数据,避免为表分享图片。 请提供足够的代码,以便其他人更好地理解或重现问题。 中间范围是什么意思?这些行有 ID 吗? 【参考方案1】:

有几种方法可以实现,这里是一种:

library(tidyverse)
genomic_ranges %>%
  group_by(sample_ID) %>%
  summarize(start = min(start),
            end = max(end),
            feature = feature[1])

给出:

# A tibble: 3 x 4
  sample_ID start   end feature
  <chr>     <dbl> <dbl> <chr>  
1 A             1     5 normal 
2 B            20    70 DUP    
3 C           250   400 DUP

【讨论】:

这很简单!感谢您的回答@deschen!【参考方案2】:

经过大量搜索、反复试验以及与同事聊天后,我找到了另一种折叠范围的方法,而且通常这是我所期望的非常简单的解决方案。我只是使用了 valr 包的 bed_merge() 函数。

这是特定于基因组范围的(bed_merge() 需要染色体编号 - 内置特异性耶!),当样本之间唯一的唯一标识符是范围时特别有用。仍然需要按 sample_ID 分组,因为样本之间的范围可能重叠。唯一的缺点是这个函数不会在你的 df 中保留任何额外的数据,所以一个键对于合并你的元数据和范围很有用。

这是一个例子:

library(tidyverse)
library(valr)
df <- data.frame(sample_ID = c("A", "B", "B", "B", "B", "B", "B", "B", "C", "C"),
                 chrom = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1),
                 start = c(1, 20, 30, 40, 70, 90, 100, 110, 130, 250),
                 end =  c(5, 30, 40, 70, 80, 100, 110, 130, 150, 400),
                 feature = c("normal", "DUP", "DUP", "DUP", "DUP", "DUP", "DUP", "DUP", "DUP", "DUP"))

> df    
   sample_ID chrom start end feature
1          A     1     1   5  normal
2          B     1    20  30     DUP
3          B     1    30  40     DUP
4          B     1    40  70     DUP
5          B     1    70  80     DUP
6          B     1    90 100     DUP
7          B     1   100 110     DUP
8          B     1   110 130     DUP
9          C     1   130 150     DUP
10         C     1   250 400     DUP



collapsed_df <- df %>%
  group_by(sample_ID) %>%
  bed_merge()

> collapsed_df
# A tibble: 5 × 4
# Groups:   sample_ID [3]
  sample_ID chrom start   end
  <chr>     <dbl> <int> <int>
1 A             1     1     5
2 B             1    20    80
3 B             1    90   130
4 C             1   130   150
5 C             1   250   400

【讨论】:

以上是关于在两个单独的列中折叠具有连续范围的行的主要内容,如果未能解决你的问题,请参考以下文章

如果所有行的列中只有一个值,则折叠 Pandas 数据框中的行

MySQL - 在单独的列中跟踪重复记录类型

Pandas Dataframe 保留日期在两个日期之间的行(单独的列)

比较另一个 id 下属于不同 ids 组的行并将结果打印在单独的列中

如何在没有交叉产品的情况下从 BigQuery 中的两列中取消嵌套两个列表,作为单独的行

PySpark - 如何根据列中的两个值从数据框中过滤出连续的行块