计算组之间的重叠次数

3

我有两个大数据集,看起来像这样。

library(tidyverse)


dat1 <- tibble(chrom=c(rep(c("Chr1","Chr2"),each=5)),
               start=c(9885,11944, 13271,15104,19059,25793,97514,104718,118862,120950),
               end=c(11008,17644,20164,23807,25264,106001,119205, 121576,124981,138514)
)

head(dat1,n=4)
#> # A tibble: 10 × 3
#>    chrom  start    end
#>    <chr>  <dbl>  <dbl>
#>  1 Chr1    9885  11008
#>  2 Chr1   11944  17644
#>  3 Chr1   13271  20164
#>  4 Chr1   15104  23807


dat2 <- tibble(chrom=c(rep(c("Chr1","Chr2"),each=5)),
               start=c(9885,11944, 13271,15104,19059,25793,97514,104718,118862,120950),
               end=c(10203,12546,13669,15638,19283,26703,97773, 105102,119388,121331)
               )

head(dat2, n=4)
#> # A tibble: 10 × 3
#>    chrom  start    end
#>    <chr>  <dbl>  <dbl>
#>  1 Chr1    9885  10203
#>  2 Chr1   11944  12546
#>  3 Chr1   13271  13669
#>  4 Chr1   15104  15638

使用 reprex v2.0.2 于2022-12-05创建

我想根据chrom对我的数据进行分组,并查找从dat2的Chr1的范围[start-end]与dat1的Chr1的范围[start-end]重叠的内容。

我尝试过的方法

我已经找到了一个很好的包来处理它,但我觉得我需要将数据集分成不同染色体的数据框来进行比较。

library(plyranges)

dat1 <- dat1 %>% 
  as_iranges()

dat2  <- dat2 %>% 
  as_iranges()

dat1 %>% 
  mutate(n_olap = count_overlaps(., dat2),
                 n_olap_within = count_overlaps_within(., dat2))

IRanges object with 10 ranges and 3 metadata columns:
           start       end     width |       chrom    n_olap n_olap_within
       <integer> <integer> <integer> | <character> <integer>     <integer>
   [1]      9885     11008      1124 |        Chr1         1             0
   [2]     11944     17644      5701 |        Chr1         3             0
   [3]     13271     20164      6894 |        Chr1         3             0
   [4]     15104     23807      8704 |        Chr1         2             0
   [5]     19059     25264      6206 |        Chr1         1             0
   [6]     25793    106001     80209 |        Chr2         3             0
   [7]     97514    119205     21692 |        Chr2         3             0
   [8]    104718    121576     16859 |        Chr2         3             0
   [9]    118862    124981      6120 |        Chr2         2             0
  [10]    120950    138514     17565 |        Chr2         1             0


为了从这里获得我想要的内容,我需要过滤我的数据并进行比较。但是应该有一种方法或dplyr技巧来找到解决方案。
dat1 <- dat1 %>% 
  as_iranges() %>% 
  filter(chrom=="Chr1")

dat2  <- dat2 %>% 
  as_iranges() %>% 
  filter(chrom=="Chr1")

dat1 %>% 
  mutate(n_olap = count_overlaps(., dat2),
                 n_olap_within = count_overlaps_within(., dat2))

有没有一种方法只比较染色体?

2个回答

3
如果您有大量的数据集,可以考虑使用data.table这种方式:
library(data.table)

dat1 <- data.frame(chrom=c(rep(c("Chr1","Chr2"),each=5)),
               start=c(9885,11944, 13271,15104,19059,25793,97514,104718,118862,120950),
               end=c(11008,17644,20164,23807,25264,106001,119205, 121576,124981,138514)
)

dat2 <- data.frame(chrom=c(rep(c("Chr1","Chr2"),each=5)),
               start=c(9885,11944, 13271,15104,19059,25793,97514,104718,118862,120950),
               end=c(10203,12546,13669,15638,19283,26703,97773, 105102,119388,121331)
               )

setDT(dat1)
setDT(dat2)

dat1[dat2, cbind(
  .SD[i.end >= start & end >= i.start],
  start2 = i.start,
  end2 = i.end), on="chrom", by=.EACHI][!is.na(start)]
#>     chrom  start    end start2   end2
#>  1:  Chr1   9885  11008   9885  10203
#>  2:  Chr1  11944  17644  11944  12546
#>  3:  Chr1  13271  20164  13271  13669
#>  4:  Chr1  15104  23807  15104  15638
#>  5:  Chr1  19059  25264  19059  19283
#>  6:  Chr2  25793 106001  25793  26703
#>  7:  Chr2  97514 119205  97514  97773
#>  8:  Chr2 104718 121576 104718 105102
#>  9:  Chr2  97514 119205 118862 119388
#> 10:  Chr2 118862 124981 118862 119388
#> 11:  Chr2 120950 138514 120950 121331

编辑 我对重叠匹配进行了修正。感谢r2evans的指正。


1
你确定这计算了所有的重叠部分吗?例如,如果一个“起始-结束”范围完全在另一个范围之外,“between(.)”可能会返回false。 - r2evans
1
好的观点。 i.end >= start&end> = i.start 这样行吗? - Ric
另外,dat1中的NA必须被过滤,因为连接是与所有dat2进行的。我修改了答案... - Ric

3

我将继续使用RicVillalba提出的data.table主题,但我认为foverlaps函数更适用于像这样的任务(尤其是在处理较大数据集时)。

library(data.table)
setDT(dat1)
setDT(dat2)
setkey(dat1, chrom, start, end)
setkey(dat2, chrom, start, end)
dat1[, id := .I]
foverlaps(dat1, dat2)
#      chrom  start    end i.start  i.end    id
#     <char>  <num>  <num>   <num>  <num> <int>
#  1:   Chr1   9885  10203    9885  11008     1
#  2:   Chr1  11944  12546   11944  17644     2
#  3:   Chr1  13271  13669   11944  17644     2
#  4:   Chr1  15104  15638   11944  17644     2
#  5:   Chr1  13271  13669   13271  20164     3
#  6:   Chr1  15104  15638   13271  20164     3
#  7:   Chr1  19059  19283   13271  20164     3
#  8:   Chr1  15104  15638   15104  23807     4
#  9:   Chr1  19059  19283   15104  23807     4
# 10:   Chr1  19059  19283   19059  25264     5
# ---                                          
# 13:   Chr2 104718 105102   25793 106001     6
# 14:   Chr2  97514  97773   97514 119205     7
# 15:   Chr2 104718 105102   97514 119205     7
# 16:   Chr2 118862 119388   97514 119205     7
# 17:   Chr2 104718 105102  104718 121576     8
# 18:   Chr2 118862 119388  104718 121576     8
# 19:   Chr2 120950 121331  104718 121576     8
# 20:   Chr2 118862 119388  118862 124981     9
# 21:   Chr2 120950 121331  118862 124981     9
# 22:   Chr2 120950 121331  120950 138514    10

(请注意,除了要求键之外,顺序也很重要:最后两个键必须是要检查重叠的范围的“起始”和“结束”。我添加了chrom以确保我们按染色体进行操作。)
那是开始。我将id列添加到dat1中,以便我们可以高效地返回到原始列。如果您仔细检查列,请注意i.*列来自dat1,因此这些是我们想要保留的列。
将其扩展以执行您希望完成的聚合操作,
overlaps <- foverlaps(dat1, dat2)[, .(n_olaps = .N, n_within = sum(between(i.start, start, end) & between(i.end, start, end))), by = .(id)]
overlaps
#        id n_olaps n_within
#     <int>   <int>    <int>
#  1:     1       1        0
#  2:     2       3        0
#  3:     3       3        0
#  4:     4       2        0
#  5:     5       1        0
#  6:     6       3        0
#  7:     7       3        0
#  8:     8       3        0
#  9:     9       2        0
# 10:    10       1        0

dat1 <- overlaps[dat1, on = .(id)]
dat1
#        id n_olaps n_within  chrom  start    end
#     <int>   <int>    <int> <char>  <num>  <num>
#  1:     1       1        0   Chr1   9885  11008
#  2:     2       3        0   Chr1  11944  17644
#  3:     3       3        0   Chr1  13271  20164
#  4:     4       2        0   Chr1  15104  23807
#  5:     5       1        0   Chr1  19059  25264
#  6:     6       3        0   Chr2  25793 106001
#  7:     7       3        0   Chr2  97514 119205
#  8:     8       3        0   Chr2 104718 121576
#  9:     9       2        0   Chr2 118862 124981
# 10:    10       1        0   Chr2 120950 138514

我选择在创建重叠并将其连接回dat1中,以防还需要保留其他列。如果数据集太大无法进行临时复制,则可以更加就地地在dat1中完成此操作。


1
这很美丽。 - LDT

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接