domaeg - 26 days ago 8
R Question

# Fast way to create a binary indicator matrix in R

I have a vector that provides how many "1" each row of a matrix has. Now I have to create this matrix out of the vector.
E.g let say I want to create a 4 x 9 matrix

`out`
with following vector
`v <- c(2,6,3,9)`
. The result should look like this

``````out
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,]    1    1    0    0    0    0    0    0    0
[2,]    1    1    1    1    1    1    0    0    0
[3,]    1    1    1    0    0    0    0    0    0
[4,]    1    1    1    1    1    1    1    1    1
``````

I've done this with a for loop but my solution is slow for a large matrix (100k x 500):

``````out <- NULL
for(i in 1:length(v)){
out <- rbind(out,c(rep(1, v[i]),rep(0,9-v[i])))
}
``````

Has anyone an idea for a faster way to create such a matrix?
Thanks!

`vapply` is usually faster than `sapply`. This assigns the desired number of ones to a length-9 vector and then transposes.

``````> t( vapply( c(2,6,3,9), function(y) { x <- numeric( length=9); x[1:y] <- 1;x}, numeric(9) ) )
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,]    1    1    0    0    0    0    0    0    0
[2,]    1    1    1    1    1    1    0    0    0
[3,]    1    1    1    0    0    0    0    0    0
[4,]    1    1    1    1    1    1    1    1    1
``````

Less than 5 seconds on an old Mac.

`````` system.time( M <- t( vapply( sample(1:500, 100000, rep=TRUE), function(y) { x <- numeric( length=500); x[1:y] <- 1;x}, numeric(500) ) ) )
user  system elapsed
3.531   1.208   4.676
``````