从块矩阵构造新的超矩阵

时间:2014-05-21 20:41:51

标签: r matrix

如何构建(在R中)由矩阵子组件构成的矩阵?

例如,从矩阵开始

A <- matrix(1:9,nrow=3,ncol=3)
B <- matrix(5:10,nrow=2,ncol=3)
C <- matrix(11:20,nrow=2,ncol=5)

我想构建一个块矩阵

A 0
B C

其中0表示具有适当尺寸的零填充块。

关于构建block-diagonal matrices还有其他问题  (Matrix::bdiag对此很好),但我找不到回答这个问题的人。

(我正在发布这个问题,因为当它被原始海报删除时,我刚刚完成了回答...)

2 个答案:

答案 0 :(得分:4)

我尝试编写通用功能。用法类似于matrix(),但第一个参数是矩阵列表(或将被回收的向量)。它没有所有的花里胡哨(dimnamesbyrow),但它是一个不错的开始。我不会惊讶地发现一个包中已经存在更好更完整的功能,但至少这是一个有趣的练习:

supermatrix <- function(list.of.mat, nrow = 1L, ncol = 1L) {
   stopifnot(length(list.of.mat) == nrow * ncol)
   is.mat <- vapply(list.of.mat, is.matrix, logical(1L))
   is.vec <- vapply(list.of.mat, is.vector, logical(1L))
   if (any(!is.mat & !is.vec)) stop("the list items must be matrices or vectors")
   is.mat.mat <- matrix(is.mat, nrow, ncol)
   if (any(rowSums(is.mat.mat) == 0L))
      stop("we need at least one matrix per super row")
   if (any(colSums(is.mat.mat) == 0L))
      stop("we need at least one matrix per super column")
   na.mat <- matrix(NA, nrow, ncol)
   nrow.mat <- replace(na.mat, is.mat, vapply(list.of.mat[is.mat], nrow, integer(1L)))
   ncol.mat <- replace(na.mat, is.mat, vapply(list.of.mat[is.mat], ncol, integer(1L)))
   is.not.uniq <- function(x) length(table(x)) > 1L
   if (any(apply(nrow.mat, 1, is.not.uniq))) stop("row dim mismatch")
   if (any(apply(ncol.mat, 2, is.not.uniq))) stop("col dim mismatch")
   nrow.vec <- rowMeans(nrow.mat, na.rm = TRUE)
   ncol.vec <- colMeans(ncol.mat, na.rm = TRUE)
   nrow.mat <- matrix(nrow.vec, nrow, ncol, byrow = FALSE)
   ncol.mat <- matrix(ncol.vec, nrow, ncol, byrow = TRUE)
   all.mat <- Map(matrix, list.of.mat, nrow.mat, ncol.mat)
   i1.idx <- unlist(Map(rep, row(na.mat), lapply(all.mat, length)))
   j1.idx <- unlist(Map(rep, col(na.mat), lapply(all.mat, length)))
   i2.idx <- unlist(lapply(all.mat, row))
   j2.idx <- unlist(lapply(all.mat, col)) 
   o.idx <- order(j1.idx, j2.idx, i1.idx, i2.idx)
   matrix(unlist(all.mat)[o.idx], sum(nrow.vec), sum(ncol.vec))
}

使用示例:

A <- matrix(1:9,nrow=3,ncol=3)
B <- matrix(5:10,nrow=2,ncol=3)
C <- matrix(11:20,nrow=2,ncol=5)

supermatrix(list(A, B, 0, C), 2, 2)
supermatrix(list(A, B, A, 1, 0, C, 2, C), 4, 2)

答案 1 :(得分:0)

我们需要一个与A和C具有兼容尺寸的零矩阵:

z <- matrix(0,nrow=nrow(A),ncol=ncol(C))

现在我们只使用rbind()cbind()

rbind(cbind(A,z),cbind(B,C))