[R] fast way to create composite matrix based on mixed indices?

Dénes Tóth toth.denes at ttk.mta.hu
Thu Sep 17 23:22:56 CEST 2015


Hi Matt,

you could use matrix indexing. Here is a possible solution, which could 
be optimized further (probably).

# The old matrix
(old.mat <- matrix(1:30,nrow=3,byrow=TRUE))
# matrix of indices
index <- matrix(c(1,1,1,4,
                   1,3,5,10,
                   2,2,1,3,
                   2,1,4,8,
                   2,3,9,10),
                 nrow=5,byrow=TRUE,
                 dimnames=list(NULL,
                               c('new.mat.row','old.mat.row',
                                 'old.mat.col.start','old.mat.col.end')))
# expected result
new.mat <- matrix(c(1:4,25:30,11:13,4:8,29:30),
                   byrow=TRUE, nrow=2)
#
# column indices
ind <- mapply(seq, index[, 3], index[,4],
               SIMPLIFY = FALSE, USE.NAMES = FALSE)
ind_len <- vapply(ind, length, integer(1))
ind <- unlist(ind)

#
# old indices
old.ind <- cbind(rep(index[,2], ind_len), ind)
#
# new indices
new.ind <- cbind(rep(index[,1], ind_len), ind)
#
# create the new matrix
result <- matrix(NA_integer_, max(index[,1]), max(index[,4]))
#
# fill the new matrix
result[new.ind] <- old.mat[old.ind]
#
# check the results
identical(result, new.mat)


HTH,
   Denes




On 09/17/2015 10:36 PM, Matthew Keller wrote:
> HI all,
>
> Sorry for the title here but I find this difficult to describe succinctly.
> Here's the problem.
>
> I want to create a new matrix where each row is a composite of an old
> matrix, but where the row & column indexes of the old matrix change for
> different parts of the new matrix. For example, the second row of new
> matrix (which has , e.g., 10 columns) might be columns 1 to 3 of row 2 of
> old matrix, columns 4 to 8 of row 1 of old matrix, and columns 9 to 10 of
> row 3 of old matrix.
>
> Here's an example in code:
>
> #The old matrix
> (old.mat <- matrix(1:30,nrow=3,byrow=TRUE))
>
> #matrix of indices to create the new matrix from the old one.
> #The 1st column gives the row number of the new matrix
> #the 2nd gives the row of the old matrix that we're going to copy into the
> new matrix
> #the 3rd gives the starting column of the old matrix for the row in col 2
> #the 4th gives the end column of the old matrix for the row in col 2
> index <- matrix(c(1,1,1,4,
>                    1,3,5,10,
>                    2,2,1,3,
>                    2,1,4,8,
>                    2,3,9,10),
>                  nrow=5,byrow=TRUE,
>
> dimnames=list(NULL,c('new.mat.row','old.mat.row','old.mat.col.start','old.mat.col.end')))
>
> I will be given old.mat and index and want to create new.mat from them.
>
> I want to create a new.matrix of two rows that looks like this:
> new.mat <- matrix(c(1:4,25:30,11:13,4:8,29:30),byrow=TRUE,nrow=2)
>
> So here, the first row of new.mat is columns 1 to 4 of row 1 of the old.mat
> and columns 5 to 10 of row 3 of old.mat.
>
> new.mat and old.mat will always have the same number of columns but the
> number of rows could differ.
>
> I could accomplish this in a loop, but the real problem is quite large
> (new.mat might have 1e8 elements), and so a for loop would be prohibitively
> slow.
>
> I may resort to unix tools and use a shell script, but wanted to first see
> if this is doable in R in a fast way.
>
> Thanks in advance!
>
> Matt
>
>



More information about the R-help mailing list