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

时间:2016-01-26 02:46:49

标签: r list range intervals

我试图将一系列间隔折叠成更少,同样有意义的间隔。

例如考虑这个间隔列表

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
    )

enter image description here

如何减少Intervals列表以显示与地图上显示的信息相同的信息? (表现问题)

以上示例的所需输出是

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

2 个答案:

答案 0 :(得分:2)

您需要的是reduce包中的IRanges功能。

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

答案 1 :(得分:0)

基础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,但是, ,这是可读的。可以随意重写/优化。)