# File: combmat.R
# Purpose: add up matrices with different dimensions
# Input: a list of 2-dimensional matrices
# Output: a combined matrix
# Author: Kay Cichini
# Date: Nov. 23th 2011
combmat <- function(m_l = list(NA)){
n_m <- length(m_l) # no. of matrices used
rownames_l <- lapply(m_l, rownames) # list of rownames
colnames_l <- lapply(m_l, colnames) # list of colnames
rownames_new <- unique(unlist(rownames_l)) # new, general rownames
colnames_new <- unique(unlist(colnames_l)) # new, general colnames
dimnames_new = list(rownames_new, colnames_new)
m_new <- matrix(nrow = length(rownames_new),
ncol = length(colnames_new),
data = 0,
dimnames = dimnames_new)
m_interm_arr <- # array of intermediate
array(m_new, dim = c(length(rownames_new), # matrices with same no. of
length(colnames_new), n_m), # dimensions as elements in
dimnames = dimnames_new) # list of input matrices
# take i-th element in list of imput matrices and add
# its values according to the appropiate row and col indexes
# in i-th dimension (i-th matrix) within array:
for (i in 1:n_m) {
m_interm_arr[,,i][rownames_l[[i]], colnames_l[[i]]] <- m_l[[i]]
}
return(apply(m_interm_arr, c(1,2), sum))
}
# Example:
print(m1 <- matrix(sample(1:40), 4, 10, dimnames = list(1:4,1:10)))
print(m2 <- matrix(sample(1:40), 10, 4, dimnames = list(1:10,1:4)))
combmat(m_l = list(m1, m2))
It is very likely that someone else may come to a more effective approach - I'd be happy to here about improvements or if there is a package/function doing the same...
Hi Kay,
ReplyDeleteI like your solution, but how about the following (using your m1 and m2 matrices)?
library(reshape2)
m_comb <- do.call(rbind, lapply(list(m1, m2), melt))
acast(m_comb, m_comb$Var1~m_comb$Var2, sum)
However, if colname classes are mixed, this re-sorts columns alphabetically, with numbers stored as character... although mixedorder in gtools could be used to sort a bit more sensibly:
library(gtools)
m_sum[, mixedorder(colnames(m_sum))]
Cheers,
John
Hi John,
ReplyDeleteMany thanks for your input. Actually, I was searching for something like this! In the end, my post my serve as an example for yielding equal results with build-in functions and by hand..
Best regards,
Kay