使用起始和结束位置从向量中创建一个序列

4

给定两个长度相等的矢量:f.start 和 f.end,我想构建一个序列(逐一),从 f.start[1]:f.end[1]f.start[2]:f.end[2],...,最终到 f.start[n]:f.end[n]

这里有一个只有6行的示例。

   f.start  f.end
[1,]   45739 122538
[2,]  125469 202268
[3,]  203563 280362
[4,]  281657 358456
[5,]  359751 436550
[6,]  437845 514644

简单来说,可以使用循环实现,但对于较大的数据集(行数>2000),速度极慢。
f.start<-c(45739,125469,203563,281657,359751,437845)
f.end<-c(122538,202268,280362,358456,436550,514644)
f.ind<-f.start[1]:f.end[1]
for (i in 2:length(f.start))
{
 f.ind.temp<-f.start[i]:f.end[i]
 f.ind<-c(f.ind,f.ind.temp)
}

我认为可以使用apply()函数来完成这个任务,但我还没有弄清楚如何在apply()中传递两个不同的参数,希望能得到一些指导。

2个回答

8
您可以尝试使用mapplyMap,它们可以同时迭代您的两个向量。您需要将函数作为第一个参数提供:
vec1 = c(1,33,50)
vec2 = c(10,34,56)

unlist(Map(':',vec1, vec2))
# [1]  1  2  3  4  5  6  7  8  9 10 33 34 50 51 52 53 54 55 56

只需将vec1vec2替换为f.startf.end,前提是all(f.start<=f.end)


3

由于您正在增加向量f.ind,所以循环将变得缓慢。如果预先分配输出向量的长度,您还将获得速度增加。

# Some data (of length 3000)
set.seed(1)
f.start <- sample(1:10000, 3000)
f.end <- f.start + sample(1:200, 3000, TRUE)

# Functions
op <- function(L=1) {
        f.ind <- vector("list", L)
            for (i in 1:length(f.start)) {
                f.ind[[i]] <- f.start[i]:f.end[i]
             }
        unlist(f.ind)
        }

op2 <- function() unlist(lapply(seq(f.start), function(x) f.start[x]:f.end[x]))
col <- function() unlist(mapply(':',f.start, f.end))

# check output
all.equal(op(), op2())
all.equal(op(), col())

一些基准测试
library(microbenchmark)

# Look at the effect of pre-allocating
microbenchmark(op(L=1), op(L=1000), op(L=3000), times=500)
#Unit: milliseconds
#         expr       min        lq     mean    median        uq       max neval cld
#    op(L = 1) 46.760416 48.741080 52.29038 49.636864 50.661506 113.08303   500   c
# op(L = 1000) 41.644123 43.965891 46.20380 44.633016 45.739895  94.88560   500  b 
# op(L = 3000)  7.629882  8.098691 10.10698  8.338387  9.963558  60.74152   500 a  

# Compare methods - the loop actually performs okay
# I left the original loop out
microbenchmark(op(L=3000), op2(), col(), times=500)
#Unit: milliseconds
#        expr      min       lq     mean   median        uq      max neval cld
# op(L = 3000) 7.778643 8.123136 10.119464 8.367720 11.402463 62.35632   500   b
#        op2() 6.461926 6.762977  8.619154 6.995233 10.028825 57.55236   500  a 
#        col() 6.656154 6.910272  8.735241 7.137500  9.935935 58.37279   500  a 

一个循环在速度方面表现良好,但是上校的代码当然更加清晰。这里的*apply函数虽然不能显著加速计算,但它们可以提供更加整洁的代码,并消除了预先分配的需要。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接