如果我知道范围,则在 R 中填充或填充数据框

问题描述 投票:0回答:3

我正在寻找类似于 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"))
r dplyr bioinformatics plyr
3个回答
0
投票

这是一种仅使用“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


0
投票

使用

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

0
投票

在基地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

© www.soinside.com 2019 - 2024. All rights reserved.