简体   繁体   中英

How to append a vector to a vector r - in a vectorized style

We all know that appending a vector to a vector within a for loop in R is a bad thing because it costs time. A solution would be to do it in a vectorized style. Here is a nice example by Joshua Ulrich. It is important to first create a vector with known length and then fill it up, instead of appending each new piece to an existing piece within the loop.

Still, in his example he demonstrates 'only' how to append one data piece at a time. I am now fighting with the idea to fill a vector with vectors - not scalars.

Imagine I have a vector with a length of 100

vector <- numeric(length=100)

and a smaller vector that would fit 10 times into the first vector

vec <- seq(1,10,1)

How would I have to construct a loop that adds the smaller vector to the large vector without using c() or append ?

EDIT: This example is simplified - vec does not always consist of the same sequence but is generated within a for loop and should be added to vector.

You could just use normal vector indexing within the loop to accomplish this:

vector <- numeric(length=100)
for (i in 1:10) {
  vector[(10*i-9):(10*i)] <- 1:10
}
all.equal(vector, rep(1:10, 10))
# [1] TRUE

Of course if you were just trying to repeat a vector a certain number of times rep(vec, 10) would be the preferred solution.

A similar approach, perhaps a little more clear if your new vectors are of variable length:

# Let's over-allocate so that we now the big vector is big enough
big_vec = numeric(1e4)

this.index = 1

for (i in 1:10) {
    # Generate a new vector of random length
    new_vec = runif(sample(1:20, size = 1))
    # Stick in in big_vec by index
    big_vec[this.index:(this.index + length(new_vec) - 1)] = new_vec
    # update the starting index
    this.index = this.index + length(new_vec)
}

# truncate to only include the added values   
big_vec = big_vec[1:(this.index - 1)]

As @josilber suggested in comments, lists would be more R-ish. This is a much cleaner approach, unless the new vector generation depends on the previous vectors, in which case the for loop might be necessary.

vec_list = list()
for (i in 1:10) {
    # Generate a new vector of random length
    vec_list[[i]] = runif(sample(1:20, size = 1))
}

# Or, use lapply
vec_list = lapply(1:10, FUN = function(x) {runif(sample(1:20, size = 1))})

# Then combine with do.call
do.call(c, vec_list)

# or more simply, just unlist
unlist(vec_list)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM