[英]Find which column ranges overlap after grouping in R
我有一个看起来像这样的巨大数据框。
我想group_by(chr)
,然后为每个chr
找到
library(dplyr)
df1 <- tibble(chr=c(1,1,2,2),
start1=c(100,200,100,200),
end1=c(150,400,150,400),
species=c("Penguin"),
start2=c(200,200,500,1000),
end2=c(250,240,1000,2000)
)
df1
#> # A tibble: 4 × 6
#> chr start1 end1 species start2 end2
#> <dbl> <dbl> <dbl> <chr> <dbl> <dbl>
#> 1 1 100 150 Penguin 200 250
#> 2 1 200 400 Penguin 200 240
#> 3 2 100 150 Penguin 500 1000
#> 4 2 200 400 Penguin 1000 2000
创建于 2023-01-05,使用reprex v2.0.2
我希望我的数据看起来像这样。 本质上我想检查 range2 是否与任何 range1 重叠。 新数据没有改变问题,但证明检查代码
# A tibble: 4 × 6
chr start1 end1 species start2 end2 OVERLAP
1 100 150 Penguin 200 250 TRUE
1 200 400 Penguin 200 240 TRUE
2 100 150 Penguin 500 1000 FALSE
2 200 400 Penguin 1000 2000 FALSE
我与 ivs ivs
和iv_overlaps
进行了多次斗争,但没有成功获得我想要的东西。
主要编辑:
当我在真实数据中应用任何代码时,我没有得到我想要的结果,我很困惑。 为什么? 新的数据集不改题,但证明检查代码
data <- tibble::tribble(
~chr, ~start1, ~end1, ~strand, ~gene, ~start2, ~end2,
"Chr2", 2739, 2840, "+", "A", 740, 1739,
"Chr2", 12577, 12678, "+", "B", 10578, 11577,
"Chr2", 22431, 22532, "+", "C", 20432, 21431,
"Chr2", 32202, 32303, "+", "D", 30203, 31202,
"Chr2", 42024, 42125, "+", "E", 40025, 41024,
"Chr2", 51830, 51931, "+", "F", 49831, 50830,
"Chr2", 82061, 84742, "+", "G", 80062, 81061,
"Chr2", 84811, 86692, "+", "H", 82812, 83811,
"Chr2", 86782, 88106, "-", "I", 88107, 89106,
"Chr2", 139454, 139555, "+", "J", 137455, 138454,
)
data %>%
group_by(chr) %>%
mutate(overlap = any(iv_overlaps(iv(start1, end1), iv(start2, end2))))
然后它给出了 output
chr start1 end1 strand gene start2 end2 overlap
<chr> <dbl> <dbl> <chr> <chr> <dbl> <dbl> <lgl>
1 Chr2 2739 2840 + A 740 1739 TRUE
2 Chr2 12577 12678 + B 10578 11577 TRUE
3 Chr2 22431 22532 + C 20432 21431 TRUE
4 Chr2 32202 32303 + D 30203 31202 TRUE
5 Chr2 42024 42125 + E 40025 41024 TRUE
6 Chr2 51830 51931 + F 49831 50830 TRUE
7 Chr2 82061 84742 + G 80062 81061 TRUE
8 Chr2 84811 86692 + H 82812 83811 TRUE
9 Chr2 86782 88106 - I 88107 89106 TRUE
10 Chr2 139454 139555 + J 137455 138454 TRUE
这是错误的。 它们可能是间接匹配,但没有直接重叠。
场景 1:重叠的逐元素检测
library(dplyr)
df1 %>%
group_by(chr) %>%
mutate(OVERLAP = any(start1 <= end2 & end1 >= start2)) %>%
ungroup()
# # A tibble: 4 × 7
# chr start1 end1 species start2 end2 OVERLAP
# <dbl> <dbl> <dbl> <chr> <dbl> <dbl> <lgl>
# 1 1 100 150 Penguin 200 250 TRUE
# 2 1 200 400 Penguin 200 240 TRUE
# 3 2 100 150 Penguin 500 1000 FALSE
# 4 2 200 400 Penguin 1000 2000 FALSE
场景 2:用于重叠排序的逐元素检测
如果间隔是定向的,即end
可以小于start
,那么您需要在确定重叠之前进行排序。
df1 %>%
group_by(chr) %>%
mutate(OVERLAP = any(pmin(start1, end1) <= pmax(start2, end2) &
pmax(start1, end1) >= pmin(start2, end2)))
场景 3:重叠排序的交叉检测
此外,如果您想检查一个区间(start1, end1)
是否与任何区间(start2, end2)
重叠,因为ivs::iv_overlaps()
有效,那么您可以使用purrr::map2
来实现它。
df1 %>%
group_by(chr) %>%
mutate(OVERLAP = any(
purrr::map2_lgl(start1, end1,
~ any(min(.x, .y) <= pmax(start2, end2) &
max(.x, .y) >= pmin(start2, end2)))
))
您的问题有多种解释,因此这里有三种可能的情况:
[start1, end1]
是否与[start2, end2]
中的任何一个重叠。[start1, end1]
与任何[start2, end2]
重叠。[start1, end1]
是否与其对应的[start2, end2]
(同一行上的那个)重叠。 在这三种情况下,您可以使用ivs::iv_overlaps
。
情况1
iv_overlaps
将在每个组内检测[start1, end1]
中定义的间隔是否以任何方式与任何间隔[start2, end2]
重叠。 它将返回长度为[start1, end1]
的逻辑向量。
library(ivs)
library(dplyr)
df1 %>%
group_by(chr) %>%
mutate(overlap = iv_overlaps(iv(start1, end1), iv(start2, end2)))
# A tibble: 4 × 7
# Groups: chr [2]
chr start1 end1 species start2 end2 overlap
<dbl> <dbl> <dbl> <chr> <dbl> <dbl> <lgl>
1 1 100 150 Penguin 200 250 FALSE
2 1 200 400 Penguin 160 170 TRUE
3 2 100 150 Penguin 500 1000 FALSE
4 2 200 400 Penguin 1000 2000 FALSE
案例二
如果您想知道间隔 1 中的任何(不是每个)是否与间隔 2 中的任何一个重叠(因此每组一个唯一值),您应该添加any
:
df1 %>%
group_by(chr) %>%
mutate(overlap = any(iv_overlaps(iv(start1, end1), iv(start2, end2))))
# A tibble: 4 × 7
# Groups: chr [2]
chr start1 end1 species start2 end2 overlap
<dbl> <dbl> <dbl> <chr> <dbl> <dbl> <lgl>
1 1 100 150 Penguin 200 250 TRUE
2 1 200 400 Penguin 160 170 TRUE
3 2 100 150 Penguin 500 1000 FALSE
4 2 200 400 Penguin 1000 2000 FALSE
案例三
如果您想要按行重叠检测,那么您应该将map2
与iv_overlaps
一起使用:
df1 %>%
group_by(chr) %>%
mutate(overlap = map2_lgl(iv(start1, end1), iv(start2, end2), iv_overlaps))
# A tibble: 4 × 7
# Groups: chr [2]
chr start1 end1 species start2 end2 overlap
<dbl> <dbl> <dbl> <chr> <dbl> <dbl> <lgl>
1 1 100 150 Penguin 200 250 FALSE
2 1 200 400 Penguin 160 170 FALSE
3 2 100 150 Penguin 500 1000 FALSE
4 2 200 400 Penguin 1000 2000 FALSE
比较顺序
实际上,如果要将第二个间隔与第一个间隔进行比较,应该使用iv_overlaps(interval2, interval1)
:
# A tibble: 4 × 7
# Groups: chr [2]
chr start1 end1 species start2 end2 overlap
<dbl> <dbl> <dbl> <chr> <dbl> <dbl> <lgl>
1 1 100 150 Penguin 200 250 TRUE
2 1 200 400 Penguin 160 170 FALSE
3 2 100 150 Penguin 500 1000 FALSE
4 2 200 400 Penguin 1000 2000 FALSE
数据
df1 <- tibble(chr=c(1,1,2,2), start1=c(100,200,100,200), end1=c(150,400,150,400), species=c("Penguin"), start2=c(200,160,500,1000), end2=c(250,170,1000,2000) )
如果要检查重叠是否发生在任一方向,则需要:
df1 %>%
group_by(chr) %>%
mutate(overlap = (max(end1) > min(start2) & min(start2) > min(start1))|
(max(end2) > min(start1) & min(start1) > min(start2)))
#> # A tibble: 4 x 7
#> # Groups: chr [2]
#> chr start1 end1 species start2 end2 overlap
#> <dbl> <dbl> <dbl> <chr> <dbl> <dbl> <lgl>
#> 1 1 100 150 Penguin 200 250 TRUE
#> 2 1 200 400 Penguin 200 240 TRUE
#> 3 2 100 150 Penguin 500 1000 FALSE
#> 4 2 200 400 Penguin 1000 2000 FALSE
创建于 2023-01-05,使用reprex v2.0.2
如果您对重叠的定义不像 Darren 的回答https://stackoverflow.com/a/75021631/11732165那样重叠,而是包含((start1 >= start2 & end1 <= end2) | (start2 >= start1 & end2 <= end1))
然后得到答案并使用你想要的逻辑。
我使用交叉连接来确保您比较同一chr
下的所有行。
不幸的是,不可否认您的测试数据中存在完全包含 -
chr start1 end1 strand gene start2 end2 overlap
7 Chr2 82061 84742 + G 80062 81061 TRUE
8 Chr2 84811 86692 + H 82812 83811 TRUE
H 的 [start2, end2] 包含在 G 的 [start1, end1] 中。
代码(请注意,如果单个chr
下有很多记录,性能会迅速下降 - 超过 200 条可能是无法忍受的,你会想要一个不涉及自交叉的实现。
check_overlap = function(df){
df %>% mutate(temp_id = 1:nrow(df)) %>%
inner_join(., ., by='chr') %>%
filter(temp_id.x != temp_id.y) %>%
mutate(overlaps = start1.x <= end2.y & end1.x >= start2.y) %>%
group_by(chr) %>%
summarise(OVERLAP = any(overlaps)) %>%
inner_join(df, by = 'chr')
}
check_containment = function(df){
df %>% mutate(temp_id = 1:nrow(df)) %>%
inner_join(., ., by='chr') %>%
filter(temp_id.x != temp_id.y) %>%
mutate(overlaps = (start1.x >= start2.y & end1.x <= end2.y) | (start2.y >= start1.x & end2.y <= end1.x)) %>%
group_by(chr) %>%
summarise(OVERLAP = any(overlaps)) %>%
inner_join(df, by = 'chr')
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.