有一个数据框,我正在使用它看起来像这样
两列表示块的开始和结束。我需要知道从0到23110906的每个位置有多少这些块存在。有时块重叠,有时可能存在一个根本没有块覆盖的区域。它就像是R中的片段。但我不需要可视化我只需要一种方法来快速找到每个位置的块数。有一个简单的方法吗?
答案 0 :(得分:4)
这里有一些数据
m = matrix(c(10, 20, 25, 30), 2)
IRanges概念为coverage()
> cvg = coverage(IRanges(start=m[,1], end=m[,2]))
> cvg
integer-Rle of length 30 with 4 runs
Lengths: 9 10 6 5
Values : 0 1 2 1
这是一个紧凑的游程编码;在第i个位置查询
> cvg[22]
integer-Rle of length 1 with 1 run
Lengths: 1
Values : 2
> runValue(cvg[22])
[1] 2
在Rle上做数学
> cvg > 1
logical-Rle of length 30 with 3 runs
Lengths: 19 6 5
Values : FALSE TRUE FALSE
或强制转换为整数向量
> as(cvg, "integer")
[1] 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 1 1 1 1 1
此
> cumsum(tabulate(m[,1], 30)) - cumsum(tabulate(m[,2], 30))
[1] 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 1 1 1 1 1 0
也会相当快。
注意这些之间的细微差别,从范围中是否包括目的的概念(IRanges:yes; tabulate:no)的差异来看。如果这些实际上是基因组坐标,则GenomicRanges是去的地方,以考虑seqname(染色体)和链。
答案 1 :(得分:3)
您正在寻找的数据结构称为interval tree,它是一种排序二进制树,包含(猜测什么)间隔,每个间隔通常有起始位置和结束位置。
我从未使用区间树来存储您需要的点,但我猜您可以将间隔定义为interval.start = interval.end
。
构建树将花费线性时间,并且查询数据帧的间隔将采用对数时间,这比pteetor的二次时间方法快得多。
Bioconductor的R包IRanges可能对您有所帮助。我会尝试函数findOverlaps()
然后table()
结果。我邀请您阅读文档,看它是否符合您的特定需求。
答案 2 :(得分:1)
我拿了那个矩阵并检查了重叠,其中只有五个间隔有任何重叠而没有任何重叠,假设它们按起始位置排序:
> sum( mat[1:28,2] > mat[2:29,1] )
[1] 5
> sum( mat[1:27,2] > mat[3:29,1] )
[1] 0
他们是哪一个?
> which( mat[1:28,2] > mat[2:29,1] )
[1] 19 21 23 25 28
因此,创建一个长达2300万个项目的向量似乎相当浪费机器资源和时间,简单地构建一个可以计算任何特定位置所在的区间数的函数会容易得多:
fchunk <- function(pos) {sum( mat[ , 1] <= pos & mat[,2] >= pos)}
#--------
> fchunk(16675330)
[1] 2
> fchunk(16675329)
[1] 1
这些是有2的区间:
sapply( which( mat[1:28,2] > mat[2:29,1] ) ,
function(int1) c( mat[int1+1, 1], mat[int1, 2] ) )
#--------
[,1] [,2] [,3] [,4] [,5]
n7 16675330 18097680 20233612 21288777 22847516
n8 16724700 18445265 20741145 22780817 22967567
答案 3 :(得分:0)
如果你真的想要每个位置的计数 - 所有23,110,906个位置 - 这段代码会告诉你。
countChunks = function(i) sum(dfrm$n7 <= i & i <= dfrm$n8)
counts = sapply(1:23110906, countChunks)
但它很慢。更快的代码需要一些巧妙的优化来消除这两行的(非常)冗余倒计时。
如果您只想在一个位置i
进行计数,只需致电countChunks(i)
。