Get seq () in R with alternating steps

The seq function in R will give me a sequence from x to y with a constant step m :

 seq(x, y, m) 

eg. seq(1,9,2) = c(1,3,5,7,9) .

What would be the most elegant way to get a sequence from x to y with alternating steps m1 and m2 , so something like "seq(x, y, c(m1, m2))" will give me c(x, x + m1, (x + m1) + m2, (x + m1 + m2) + m1, ..., y) , each time adding one of the steps (does not necessarily reach y , of course, as in seq )?

Example: x = 1; y = 19; m1 = 2; m2 = 4 x = 1; y = 19; m1 = 2; m2 = 4 x = 1; y = 19; m1 = 2; m2 = 4 and I get c(1,3,7,9,13,15,19) .

+7
r seq
source share
6 answers

I came to the solution: 1. Use cumsum with the vector c(from,rep(by,times),...) , with by repeating times = ceiling((to-from)/sum(by)) times. 2. Truncate the sequence by !(seq > to) .

  seq_alt <- function(from, to, by) { seq <- cumsum(c(from,rep(by,ceiling((to-from)/sum(by))))) return(seq[! seq > to]) } 
+6
source share

The first n terms of this sequence that you can generate with

 x = 1; m1 = 2; m2 = 4 n <- 0:10 # first 11 terms x + ceiling(n/2)*m1 + ceiling((n-1)/2)*m2 # [1] 1 3 7 9 13 15 19 21 25 27 31 
+3
source share

Here is another idea

 fun1 <- function(x, y, j, z){ if(j >= y) {return(x)}else{ s1 <- seq(x, y, j+z) s2 <- seq(x+j, y, j+z) return(sort(c(s1, s2))) } } fun1(1, 19, 2, 4) #[1] 1 3 7 9 13 15 19 fun1(1, 40, 4, 3) #[1] 1 5 8 12 15 19 22 26 29 33 36 40 fun1(3, 56, 7, 10) #[1] 3 10 20 27 37 44 54 fun1(1, 2, 2, 4) #[1] 1 
+3
source share

Here is an alternative that uses diffinv This method allows you to distribute values, since the rule is stopping, I get elements that are less than or equal to the stop value.

 seqAlt <- function(start, stop, by1, by2) { out <- diffinv(rep(c(by1, by2), ceiling(stop / (by1 + by2))), xi=start) return(out[out <= stop]) } seqAlt(1, 19, 2, 4) [1] 1 3 7 9 13 15 19 
+1
source share

perfect example of recycle vectors in R

 # 1. x = 1; y = 19; m1 = 2; m2 = 4 (x:y)[c(TRUE, rep(FALSE, m1-1), TRUE, rep(FALSE,m2-1))] # [1] 1 3 7 9 13 15 19 # 2. x = 3; y = 56; m1 = 7; m2 = 10 (x:y)[c(TRUE, rep(FALSE, m1-1), TRUE, rep(FALSE,m2-1))] # [1] 3 10 20 27 37 44 54 
+1
source share

You can use Reduce with accumulate = TRUE to iteratively add either 2 or 4:

 Reduce(`+`, rep(c(2,4), 10), init = 1, accumulate = TRUE) # [1] 1 3 7 9 13 15 19 21 25 27 31 33 37 39 43 45 49 51 55 57 61 

The number of repetitions c(2,4) will determine the length of the sequence; since it is equal to 10, the sequence is equal to a length of 20.

The purrr package has an accumulate wrapper if you prefer the syntax:

 purrr::accumulate(rep(c(2,4), 10), `+`, .init = 1) ## [1] 1 3 7 9 13 15 19 21 25 27 31 33 37 39 43 45 49 51 55 57 61 
+1
source share

All Articles