Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I add columns to expand a matrix in R

Tags:

r

matrix

Sorry I couldn't think of a more informative title, but here's my challenge. I have a matrix and I need to add columns in specific places based on parameters described by a vector. For example, if I have the following matrix:

1, 0, 1, 2, 0
0, 0, 1, 1, 1
1, 1, 0, 0, 0
2, 0, 1, 0, 2

but for a particular R package (unmarked), I need to add columns of NA in specific place. I have a vector relating the columns in the matrix:

1, 1, 1, 2, 3

Which indicates that columns 1-3 were from the same sampling period and columns 4 and 5 were from different sampling periods. I need to make the number of columns in the matrix equal the max number from the same sampling period times the number of sampling periods. In this case there are three 1s (max number of any unique value in the vector) and a total of three sampling periods (max number in the vector). So I need a matrix with 9 columns (3 x 3). Specifically, I need to add the new columns of NAs after the 4th and 5th columns. Basically, I just need columns of NAs to be placeholders to have a matrix where the number of observations (each column) is the same (=3) for each of the sample periods (indicated by the number in the vector). This is difficult to describe but in this imaginary example I would want to end up with:

1, 0, 1, 2, NA, NA, 0, NA, NA
0, 0, 1, 1, NA, NA, 1, NA, NA
1, 1, 0, 0, NA, NA, 0, NA, NA
2, 0, 1, 0, NA, NA, 2, NA, NA

this would be described by a vector that looked like:

1, 1, 1, 2, 2, 2, 3, 3, 3

although I don't actually need to produce that vector, just the matrix. Obviously, it was easy to add those columns in this case, but for my data I have a much bigger matrix that will end up with ~200 columns. Plus I will likely have to do this for numerous data sets.

Can anyone help me with a way to code this in R so that I can automate the process of expanding the matrix?

Thanks for any advice or suggestions!


EDIT: to make things a bit more similar to my actual data here is a reproducible matrix and vector similar to my current ones:

    m <- matrix(rpois(120*26, 1), nrow = 120, ncol = 26)
    v <- c(1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 5, 5, 6, 6, 6, 6, 7)
like image 308
djhocking Avatar asked Feb 04 '12 17:02

djhocking


2 Answers

Assuming m is the matrix and v is the vector, you can use something like

 t = table(v)
 size = dim(m)[1] * max(t)   # size of each block based on the longest
 matrix(unlist(lapply(names(t), function(i) {
               x = m[, v == i]                  # get the short block
               c(x, rep(NA, size - length(x)))  # extend it to size
         })), dim(m)[1])
like image 110
Simon Urbanek Avatar answered Sep 20 '22 13:09

Simon Urbanek


To modify the matrix just as you asked assuming the matrix is mat:

nr <- nrow(mat)
nas <- rep(NA, nr)
l <- lapply( 4:ncol(mat), function(x) matrix(c(mat[,x],nas,nas), nrow = nr) )
cbind(mat[,1:3], do.call(cbind,l))
like image 22
John Avatar answered Sep 16 '22 13:09

John