Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get a seq() in R with alternating steps

Tags:

r

seq

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

seq(x, y, m)

E.g. 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, such that something like "seq(x, y, c(m1, m2))" would give me c(x, x + m1, (x + m1) + m2, (x + m1 + m2) + m1, ..., y), each time adding one of the steps (not necessarily reaching up to y, of course, as in seq)?

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

like image 829
Giora Simchoni Avatar asked Jan 11 '17 09:01

Giora Simchoni


3 Answers

You could 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 times you repeat c(2,4) will determine sequence length; since it is 10 above, the sequence is length 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
like image 70
alistaire Avatar answered Oct 12 '22 01:10

alistaire


Here is an alternative that uses diffinv This method over allocates the values, so as a stopping rule, I get the elements that are less than or equal to the stopping 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
like image 28
lmo Avatar answered Oct 12 '22 00:10

lmo


I arrived the solution by: 1. Use cumsum with a vector c(from,rep(by,times),...), with by repeated 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])
 }
like image 37
raymkchow Avatar answered Oct 12 '22 01:10

raymkchow