Say I have two vectors v1
and v2
and that I want to call rbind(v1, v2)
. However, supposed length(v1)
> length(v2)
. From the documentation I have read that the shorter vector will be recycled. Here is an example of this "recycling":
> v1 <- c(1, 2, 3, 4, 8, 5, 3, 11)
> v2 <- c(9, 5, 2)
> rbind(v1, v2)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
v1 1 2 3 4 8 5 3 11
v2 9 5 2 9 5 2 9 5
- Is there any straightforward way I can stop
v2
from being recycled and instead make the remaining entries 0?
- Is there a better way to build vectors and matrices?
All help is greatly appreciated!
use the following:
rbind(v1, v2=v2[seq(v1)])
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
v1 1 2 3 4 8 5 3 11
v2 9 5 2 NA NA NA NA NA
Why it works:
Indexing a vector by a value larger than its length returns a value of NA at that index point.
#eg:
{1:3}[c(3,5,1)]
#[1] 3 NA 1
Thus, if you index the shorter one by the indecies of the longer one, you willl get all of the values of the shorter one plus a series of NA
's
A generalization:
v <- list(v1, v2)
n <- max(sapply(v, length))
do.call(rbind, lapply(v, `[`, seq_len(n)))
In case you have many vectors to rbind
finding longer and shorter vectors could be tedious. In which case this is an option:
require(plyr)
rbind.fill.matrix(t(v1), t(v2))
or,
rbind.fill(as.data.frame(t(v1)), as.data.frame(t(v2)))
Although I think Ricardo has offered a nice solution, something like this would also work applying a function to a list of the vectors you wish to bind. You could specify the character to fill with as well.
test <- list(v1,v2)
maxlen <- max(sapply(test,length))
fillchar <- 0
do.call(rbind,lapply(test, function(x) c(x, rep(fillchar, maxlen - length(x) ) )))
Or avoiding all the do.call(rbind
madness:
t(sapply(test, function(x) c(x, rep(fillchar, maxlen - length(x)))))
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#[1,] 1 2 3 4 8 5 3 11
#[2,] 9 5 2 0 0 0 0 0