Combine each element of a vector with a different vector in R

I have two vectors

x <- c(2, 3, 4) y <- rep(0, 5) 

I want to get the following output:

 > z 2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0 

How to create z ? I tried using paste and c , but nothing works. The only thing I can think of is to use for() , and it is terribly slow. I have googled this, and I'm sure the solution is there, and I just don't click on the right keywords.

UPDATE: For benchmarking purposes:

Using Nicola's solution:

  > system.time( + precipitation <- `[<-`(numeric(length(x)*(length(y)+1)),seq(1,by=length(y)+1,length.out=length(x)),x) + ) user system elapsed 0.419 0.407 0.827 

This is ridiculously fast! I have to say! Can someone please explain this to me? My for() , which I know, is always erroneous in R , would take at least one day if it even finished.

Other offers:

  > length(prate) [1] 4914594 > length(empty) [1] 207 > system.time( + precipitation <- unlist(sapply(prate, FUN = function(prate) c(prate,empty), simplify=FALSE)) + ) user system elapsed 16.470 3.859 28.904 

I had to kill

 len <- length(prate) precip2 <- c(rbind(prate, matrix(rep(empty, len), ncol = len))) 

In 15 minutes.

+7
vector r combinations
source share
5 answers

For some reason, this looks faster:

  unlist(t(matrix(c(as.list(x),rep(list(y),length(x))),ncol=2))) 

The above solution is general, in the sense that both x and y can have any value. In the case of OP, where y is only 0, this is quick as it might be:

  `[<-`(numeric(length(x)*(length(y)+1)),seq(1,by=length(y)+1,length.out=length(x)),x) #[1] 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 0 

Edit

I understand that I was very mysterious, and the code I created is not easy to track, despite the fact that it is only one line. I will explain in detail what the second decision makes.

First of all, you will notice that the resulting vector will have values ​​contained in x , plus zeros in y repeating length(x) times. Thus, it will be longer than length(x) + length(x)*length(y) or length(x)*(length(y)+1) . Thus, we create a vector with zero dimensions as long as necessary:

  res<-numeric(length(x)*(length(y)+1)) 

Now we have to put the x values ​​in res . Note that the first value of x occupies the first value in res ; the second will be after length(y)+1 from the first, etc., until all length(x) values ​​are filled. We can create an index vector in which to place the x values:

  indices<-seq.int(1,by=length(y)+1,length.out=length(x)) 

And then we do the replacement:

  res[indices]<-x 

My line was just a shortcut to the three lines above. Hope this clarifies a bit.

+5
source share

you can try this

 unlist(sapply(x, FUN = function(x) c(x,y), simplify=FALSE)) [1] 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 0 

or simpler from @docendodiscimus

 unlist(lapply(x, FUN = function(x) c(x,y))) 
+4
source share

You can also try to vectorize as follows

 len <- length(x) c(rbind(x, matrix(rep(y, len), ncol = len))) ## [1] 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 0 

A more compact but potentially slower version (contributed by @akrun) would be

 c(rbind(x, replicate(len, y))) ## [1] 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 0 
+2
source share

You can try:

  c(sapply(x, 'c', y)) #[1] 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 

Or a crazy solution with gusb and paste.

 library(functional) p = Curry(paste0, collapse='') as.numeric(strsplit(p(gsub('(.*)$', paste0('\\1',p(y)),x)),'')[[1]]) #[1] 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 0 
+1
source share

Here's another way:

 options(scipen=100) as.numeric(unlist(strsplit(as.character(x * 10^5), ""))) 

And some guidelines:

 microbenchmark({as.numeric(unlist(strsplit(as.character(x*10^5), "")))}, {unlist(t(matrix(c(as.list(x),rep(list(y),length(x))),ncol=2)))}, {unlist(sapply(x, FUN = function(x) c(x,y), simplify=FALSE))}, times=100000) Unit: microseconds expr { as.numeric(unlist(strsplit(as.character(x * 10^5), ""))) } { unlist(t(matrix(c(as.list(x), rep(list(y), length(x))), ncol = 2))) } { unlist(sapply(x, FUN = function(x) c(x, y), simplify = FALSE)) } min lq mean median uq max neval 9.286 10.644 12.15242 11.678 12.286 1650.133 100000 9.485 11.164 13.25424 12.288 13.067 1887.761 100000 5.607 7.429 9.21015 8.147 8.784 30457.994 100000 

And here is another idea (but it seems slow):

 r = rle(1) r$lengths = rep(c(1,5), length(x)) r$values = as.vector(rbind(x, 0)) inverse.rle(r) 
+1
source share

All Articles