在R中,从范围中提取整数的有效方法是什么?
假设我有一个范围矩阵(column1 = start,column2 = end)
1 5
3 6
10 13
我想将矩阵中所有范围的包含唯一整数存储到对象中:
1
2
3
4
5
6
10
11
12
13
这将适用于包含约4百万个范围的矩阵,因此希望有人可以提供有效的解决方案。
答案 0 :(得分:12)
假设你有start = 3,end = 7,并且你在从1开始的数字行上将每个标记为'1'
starts: 0 0 1 0 0 0 0 0 0 ...
ends + 1: 0 0 0 0 0 0 0 1 0 ...
开始的累计总和减去两端的累积总和,以及两者之间的差异,是
cumsum(starts): 0 0 1 1 1 1 1 1 1 ...
cumsum(ends + 1): 0 0 0 0 0 0 0 1 1 ...
diff: 0 0 1 1 1 1 1 0 0
并且差异中1的位置是
which(diff > 0): 3 4 5 6 7
使用制表来允许在同一位置进行多次开始/结束,
range2 <- function(ranges)
{
max <- max(ranges)
starts <- tabulate(ranges[,1], max)
ends <- tabulate(ranges[,2] + 1L, max)
which(cumsum(starts) - cumsum(ends) > 0L)
}
对于这个问题,这给出了
> eg <- matrix(c(1, 3, 10, 5, 6, 13), 3)
> range2(eg)
[1] 1 2 3 4 5 6 10 11 12 13
对于Andrie的例子来说,这是非常快的
> system.time(runs <- range2(xx))
user system elapsed
0.108 0.000 0.111
(这听起来有点像DNA序列分析,GenomicRanges可能是你的朋友;你在阅读中使用coverage
和slice
函数,也许用{{ 1}})。
答案 1 :(得分:5)
我不知道它特别有效,但如果您的范围矩阵为ranges
,则以下内容应该有效:
unique(unlist(apply(ranges, 1, function(x) x[1]:x[2])))
答案 2 :(得分:5)
使用sequence
和rep
:
x <- matrix(c(1, 5, 3, 6, 10, 13), ncol=2, byrow=TRUE)
ranges <- function(x){
len <- x[, 2] - x[, 1] + 1
#allocate space
a <- b <- vector("numeric", sum(len))
a <- rep(x[, 1], len)
b <- sequence(len)-1
unique(a+b)
}
ranges(x)
[1] 1 2 3 4 5 6 10 11 12 13
由于这只使用了矢量化代码,因此即使对于大型数据集也应该非常快。在我的机器上,一百万行的输入矩阵需要大约5秒才能运行:
set.seed(1)
xx <- sample(1e6, 1e6)
xx <- matrix(c(xx, xx+sample(1:100, 1e6, replace=TRUE)), ncol=2)
str(xx)
int [1:1000000, 1:2] 265509 372124 572853 908206 201682 898386 944670 660794 629110 61786 ...
system.time(zz <- ranges(xx))
user system elapsed
4.33 0.78 5.22
str(zz)
num [1:51470518] 265509 265510 265511 265512 265513 ...
答案 3 :(得分:3)
这不是简单的事情:
x <- matrix(c(1, 5, 3, 6, 10, 13), ncol=2, byrow=TRUE)
do.call(":",as.list(range(x)))
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13
修改强>
看起来我得到了错误的结尾,但我的答案可以修改为使用union
,虽然这只是unique
的包装:
Reduce("union",apply(x,1,function(y) do.call(":",as.list(y))))
[1] 1 2 3 4 5 6 10 11 12 13