Dnaiel
Dnaiel

Reputation: 7832

R convert vector of numbers to skipping indexes

I have a vector of widths,

ws = c(1,1,2,1,3,1)

From this vector I'd like to have another vector of this form:

indexes = c(1,2,3,5,6,7,9,11,12)

In order to create such vector I did the following for loop in R:

ws = c(1,1,2,1,3,1)
indexes = rep(0, sum(ws))
counter = 1
counter2 = 1
last = 0
for(i in 1:length(ws))
{
  if (ws[i] == 1)
  {
    indexes[counter] = counter2
    counter = counter + 1
  } else {
    for(j in 1:ws[i])
    {
      indexes[counter] = counter2
      counter = counter + 1
      counter2 = counter2+2
    }
    counter2 = counter2 - 2
  }
  counter2 = counter2+1
}

The logic is as follows, each element in ws specifies the respective number of elements in index. For example if ws is 1, the respective number of elements in indexes is 1, but if ws is > 1, let us say 3, the respective number of elements in index is 3, and the elements are skipped 1-by-1, corresponding to 3,5,7.

However, I'd like to avoid for loops since they tend to be very slow in R. Do you have any suggestions on how to achieve such results only with vector operations? or some more crantastic solution?

Thanks!

Upvotes: 5

Views: 1090

Answers (1)

Josh O'Brien
Josh O'Brien

Reputation: 162341

Here's a vectorized one-liner for you:

ws <- c(1,1,2,1,3,1)

cumsum((unlist(sapply(ws, seq_len)) > 1) + 1)
# [1]  1  2  3  5  6  7  9 11 12

You can pick it apart piece by piece, working from the inside out, to see how it works.

Upvotes: 5

Related Questions