我正在寻找类似于 bedtools subtract 但带有数据框的东西。
例如,假设我在这里将范围作为数据框:
Start End Value
0 100 P
我还有另一个数据框,已排序:
Start End Value
10 25 A
50 63 B
有没有办法像这样填写:
Start End Value
0 9 P1
10 25 A
26 49 P2
50 63 B
64 100 P3
填充第二个数据框的 P1、P2 和 P3 标签,以便覆盖整个值范围。
我尝试使用 Dplyr 的 Lag 函数并手动添加填充值,但考虑到范围可以根据基因组特征的长度(包括开始和结束坐标)而变化,我希望这个范围填充是自动的。
谢谢!
例如,这是数据的一小部分:
data_range<- data.frame(start=0, end=100, value="P")
tofill_range<- data.frame(start=c(15, 51, 70),end = c(39, 62, 79), value = c("A","B","C"))
这是一种仅使用“dyplr”来计算 data.frame 范围的方法。对于你的第二个例子,我重命名了列。我们可以做更多的工作,让它适用于任何列名。
library(tidyverse)
calc_range <- function(df1, df2) {
df3 <- df2 %>%
transmute(start = End + 1,
End = Start - 1) %>%
rename(Start = start)
start_df <- bind_rows(df1, df2, df3)
start_df %>%
select(!Value) %>%
unlist %>%
sort %>%
matrix(ncol = 2, byrow = TRUE) %>%
data.frame() %>%
rename(Start = X1, End = X2) %>%
left_join(start_df, by = c("Start", "End")) %>%
mutate(Value = ifelse(is.na(Value) | Value == "P",
paste0("P", cumsum(is.na(Value) | Value == "P")),
Value)) %>%
arrange(Start)
}
# Test 1
dfa <- tribble(
~Start, ~End, ~Value,
0, 100, "P"
)
dfb <- tribble(~Start, ~End, ~Value,
10, 25, "A",
50, 63, "B")
calc_range(dfa, dfb)
#> Start End Value
#> 1 0 9 P1
#> 2 10 25 A
#> 3 26 49 P2
#> 4 50 63 B
#> 5 64 100 P3
# Test 2
data_range <- data.frame(Start=0, End=100, Value="P")
tofill_range <- data.frame(Start=c(15, 51, 70),
End = c(39, 62, 79),
Value = c("A","B","C"))
calc_range(data_range, tofill_range)
#> Start End Value
#> 1 0 14 P1
#> 2 15 39 A
#> 3 40 50 P2
#> 4 51 62 B
#> 5 63 69 P3
#> 6 70 79 C
#> 7 80 100 P4
创建于 2023-02-23 与 reprex v2.0.2
使用
dplyr
(>= v1.1.0 for consecutive_id
)
使用
between
获取缺失的范围
library(dplyr)
ranges <- rowSums(apply(tofill_range[, 1:2], 1, function(x)
between(seq(data_range$start, data_range$end), x[1], x[2])))
as_tibble(cbind(ranges, grp = consecutive_id(ranges),
val = seq(data_range[, 1], data_range[,2]))) %>%
group_by(grp) %>%
filter(ranges == 0) %>%
summarize(start = first(val),
end = last(val),
value = paste0(data_range$value, cur_group_id())) %>%
select(-grp) %>%
bind_rows(., tofill_range) %>%
arrange(start)
# A tibble: 7 × 3
start end value
<dbl> <dbl> <chr>
1 0 14 P1
2 15 39 A
3 40 50 P2
4 51 62 B
5 63 69 P3
6 70 79 C
7 80 100 P4
在基地R:
all_ranges <- function(df1, df2){
a <- sort(c(t(df1[-3]), t(df2[-3]), t(df2[-3]) + c(-1,1)))
b <- data.frame(t(matrix(a,2)))
d <- merge(df2, setNames(b, names(df1)[-3]), all = TRUE)
replace(d, is.na(d), paste0(df1[,3], seq(sum(is.na(d)))))
}
data_range<- data.frame(start=0, end=100, value="P")
tofill_range<- data.frame(start=c(15, 51, 70),end = c(39, 62, 79), value = c("A","B","C"))
all_ranges(data_range, tofill_range)
#> start end value
#> 1 0 14 P1
#> 2 15 39 A
#> 3 40 50 P2
#> 4 51 62 B
#> 5 63 69 P3
#> 6 70 79 C
#> 7 80 100 P4
创建于 2023-02-23 与 reprex v2.0.2