R是否有从多个起点和终点生成序列的vecorized方法?我只能弄清楚如何使用某种形式的循环来做到这一点,如下所示(注意:我可以使用apply,但我希望有一个真正的矢量化解决方案)
starts <- c(1,2,3)
ends <- c(10,11,12)
mySequences <- matrix(NA, nrow = 3, ncol = 10)
for(i in 1:3){
mySequences[i,] <- seq(starts[i], ends[i], length.out = 10)
}
但理想情况下,我希望它是以下内容:
mySequences <- seq(starts, ends, length.out = 10)
谢谢!
你觉得这种事情怎么样:
outer(X=c(1:3), Y=c(0:9), FUN="+")
如果像你的例子一样,宽度都是一样的(starts = 1:3; ends = 10:8; wd=10
),那么创建一个矩阵,其中每一行都是序列1:wd
使用 R 的回收规则有效地填充矩阵
m = matrix(seq(wd) - 1, length(starts), wd, byrow=TRUE)
按每列需要递增的量缩放行,并添加开始,再次使用 R(逐列)回收
m * (ends - starts) / (wd - 1) + starts
作为函数
seqs_wd = function(starts, ends, wd=10) {
m = matrix(seq(wd) - 1, length(starts), wd, byrow=TRUE)
m * (ends - starts) / (wd - 1) + starts
}
一个简单的例子
> seqs_wd(1:3, 10:8)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 1 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000 8.000000
[2,] 2 2.777778 3.555556 4.333333 5.111111 5.888889 6.666667 7.444444
[3,] 3 3.555556 4.111111 4.666667 5.222222 5.777778 6.333333 6.888889
[,9] [,10]
[1,] 9.000000 10
[2,] 8.222222 9
[3,] 7.444444 8
并与简单的实现相比
f0 = function(starts, ends, wd=10)
mapply(seq, starts, ends, length.out=10)
一些时间
> library(microbenchmark)
> n = 1000
> starts = runif(n, 100, 200); ends = starts + runif(n, 100, 200)
> microbenchmark(seqs_wd(starts, ends), f0(starts, ends))
Unit: microseconds
expr min lq mean median uq
seqs_wd(starts, ends) 203.075 210.0705 219.3789 218.3225 223.8625
f0(starts, ends) 17037.229 17370.7835 18468.4581 17862.2775 18629.8510
max neval
326.677 100
32766.215 100
或与n = 1000000
> microbenchmark(seqs_wd(starts, ends), f0(starts, ends), times=10)
Unit: milliseconds
expr min lq mean median uq max
seqs_wd(starts, ends) 318.1302 321.2502 327.4233 322.2663 326.0085 370.875
neval
10
所以一百万个序列大约是三分之一秒。