在两个单独的列中折叠具有连续范围的行
Collapsing rows with consecutive ranges in two separate columns
非常感谢你在这方面的帮助。我正在尝试压缩一个包含 200,000 多行的数据框,其中“开始”列中一行的整数与“结束”列中的下一个连续行完全相同。作为参考,这些是染色体碱基对位置,下面是一个示例代码:
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 语句、forloops 等,我找不到方法来 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 <= EndB) and (EndA >= StartB)
我仍然会失去开始或结束位置。
*编辑:感谢大家的反馈!我已经用代码更新了问题。这些行确实具有由 sample_ID 标识的 ID。理想情况下,我希望 1 行具有 20-70 的完整范围,而不是将其分成 20-30、30-40 和 40-70 的段,分成 3 行,具有相同的 sample_ID 标识符。
有几种方法可以实现这一点,这里是一种:
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
经过大量搜索,trial/error,并与同事聊天,我找到了另一种折叠范围的方法,通常这是我预期的非常简单的解决方案。我只是使用了 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
非常感谢你在这方面的帮助。我正在尝试压缩一个包含 200,000 多行的数据框,其中“开始”列中一行的整数与“结束”列中的下一个连续行完全相同。作为参考,这些是染色体碱基对位置,下面是一个示例代码:
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 语句、forloops 等,我找不到方法来 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 <= EndB) and (EndA >= StartB)
我仍然会失去开始或结束位置。
*编辑:感谢大家的反馈!我已经用代码更新了问题。这些行确实具有由 sample_ID 标识的 ID。理想情况下,我希望 1 行具有 20-70 的完整范围,而不是将其分成 20-30、30-40 和 40-70 的段,分成 3 行,具有相同的 sample_ID 标识符。
有几种方法可以实现这一点,这里是一种:
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
经过大量搜索,trial/error,并与同事聊天,我找到了另一种折叠范围的方法,通常这是我预期的非常简单的解决方案。我只是使用了 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