如何将间隔数据组合成 R 中更少的间隔?

How to combine intervals data into fewer intervals in R?

我正在尝试将一系列间隔折叠成更少但同样有意义的间隔。

例如考虑这个间隔列表

Intervals = list(
  c(23,34),
  c(45,48),
  c(31,35),
  c(7,16),
  c(5,9),
  c(56,57),
  c(55,58)
)

因为区间重叠,相同的区间可以用很少的向量来描述。绘制这些间隔很明显,4 个向量的列表就足够了

plot(1,1,type="n",xlim=range(unlist(Intervals)),ylim=c(0.9,1.1))
segments(
    x0=sapply(Intervals,"[",1),
    x1=sapply(Intervals,"[",2),
    y0=rep(1,length(Intervals)),
    y1=rep(1,length(Intervals)),
    lwd=10
    )

如何减少我的 Intervals 列表以携带与绘图上显示的信息相同的信息? (性能问题)

上述示例所需的输出是

Intervals = list(
  c(5,16)
  c(23,35),
  c(45,48),
  c(55,58)
)

你需要的是IRanges包中的reduce函数。

In.df <- do.call(rbind, Intervals)
library(IRanges)

In.ir <- IRanges(In.df[, 1], In.df[,2])

out.ir <- reduce(In.ir)
out.ir
# IRanges of length 4
#     start end width
# [1]     5  16    12
# [2]    23  35    13
# [3]    45  48     4
# [4]    55  58     4

基数为R的一个选项:

首先我把你的列表放在 data.frame:

ints <- as.data.frame(do.call(rbind, Intervals))
names(ints) <- c('start', 'stop')

看起来像

  start stop
1    23   34
2    45   48
3    31   35
4     7   16
5     5    9
6    56   57
7    55   58

现在,两个for循环与between进行比较,发现交叉时扩大一个区间:

for(x in 1:nrow(ints)){
  for(y in 1:nrow(ints)){
    if(between(ints$start[x], ints$start[y], ints$stop[y])){
      ints$start[x] <- ints$start[y]
      if(ints$stop[y] > ints$stop[x]){
        ints$stop[x] <- ints$stop[y]
      } else {
        ints$stop[y] <- ints$stop[x]
      }
    }
  }
}

ints 更改为

> ints
  start stop
1    23   35
2    45   48
3    23   35
4     5   16
5     5   16
6    55   58
7    55   58

简化为 unique 个案例:

ints <- unique(ints, margin = 1)

并把它们整理好

ints <- ints[order(ints$start),]

还剩下

> ints
  start stop
4     5   16
1    23   35
2    45   48
6    55   58

如果你想把它放回原来的列表中,

Intervals <- lapply(1:nrow(ints), function(x)c(ints[x,1], ints[x,2]))

(注意:您当然可以使用 *apply 代替 for,使用布尔值代替 between,使用原始列表代替 data.frame,但是,嗯,这是可读的。Rewrite/optimize随你喜欢。)