我试图将一系列间隔折叠成更少,同样有意义的间隔。
例如考虑这个间隔列表
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)
)
答案 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
,但是, ,这是可读的。可以随意重写/优化。)