Simon C.
Simon C.

Reputation: 1077

Create a sequence of pairs equally spaced

I want to create a vector composed by N pairs of real where each pairs are separated by a value S and the two elements of the pair are separate by a a value iS, that could be written like that:

V=[(X,X+iS)_1, (X+S+iS,X+S+2*iS)_2, ...  ]

So if we start from X=1, with S=1 and iS = .5 it should return:

V=[1.0,1.5,2.5,3.0,4.0,4.5]

I create this function that does exactly what i want:

myseq<-function(x,n,sep,isep){
  res=c(x,x+isep)
  for(i in 1:(n-1)){
      prev=res[length(res)]
      res=c(res,c(prev+sep,prev+sep+isep))
  }
  return(res)
}

With the same example than before:

> myseq(1,3,1,.5)                                                             
[1] 1.0 1.5 2.5 3.0 4.0 4.5

But I am sure it could be written in a simpler and more "functional" way, but I can't figure it out. If you have any Idea?

Upvotes: 3

Views: 707

Answers (3)

Simon C.
Simon C.

Reputation: 1077

After reviewing my question I realized that my accepted answer was maybe not the best one and that @alexis_laz in his comment came up with a short and better solution. I put them here again, and after benchmarking it seems that

My original version:

original<-function(x,n,sep,isep){
    res=c(x,x+isep)
    for(i in 1:(n-1)){
        prev=res[length(res)]
        res=c(res,c(prev+sep,prev+sep+isep))
    }
    return(res)
}

The previously accepted answer:

accepted <- function(x,isep,sep,n){
    c(rbind(seq(x,by = isep+sep, length.out = n), seq(x+isep,by = isep+sep, length.out = n))) 
}

Alexis' comment:

alexcomm <- function(x,n,sep,isep){
    cumsum(c(x, rep_len(c(isep, sep), (n * 2) - 1)))
}

And the benchmark:

                      expr        min          lq        mean      median
 alexcomm(x, n, sep, isep)     99.657    105.0090    149.4527    109.1745
  accepted(x, isep, sep, n)    130.090    137.7555    193.6189    163.2150
  original(x, n, sep, isep) 251176.761 258936.2820 268247.7626 270124.8435

Thus the solution proposed in comment is not only the short but also slightly quicker.

Upvotes: 0

Sotos
Sotos

Reputation: 51592

Here is one idea using seq,

myseq <- function(x, n, sep, isep) {
  v1 <- seq(x, n*2, sep)[c(rep(TRUE, 2), rep(FALSE, (isep/sep)-1))]
  return(v1[1:(n*2)])
  }

myseq(1,3, 0.5, 1)  
#[1] 1.0 1.5 2.5 3.0 4.0 4.5

Upvotes: 3

Chirayu Chamoli
Chirayu Chamoli

Reputation: 2076

Here is one more approach where you create 2 different vectors and then combine them alternatively in order to get the desired sequence.

myfun=function(i,x,y,n){
    c(rbind(seq(i,by = x+y, length.out = n), seq(i+x,by = x+y, length.out = n)))
}

myfun(1,0.5,1,3)
[1] 1.0 1.5 2.5 3.0 4.0 4.5

Upvotes: 2

Related Questions