问题
I'm looking for a (build-in) function, which efficiently returns the list of building blocks of a block-diagonal matrix in the following way (rather than iterating over the slots to get the list manually):
#construct bdiag-matrix
library("Matrix")
listElems <- list(matrix(1:4,ncol=2,nrow=2),matrix(5:8,ncol=2,nrow=2))
mat <- bdiag(listElems)
#get back the list
res <- theFunctionImLookingFor(mat)
The result res
yields the building blocks:
[[1]]
[,1] [,2]
[1,] 1 3
[2,] 2 4
[[2]]
[,1] [,2]
[1,] 5 7
[2,] 6 8
Edit: Regarding my use case, the list elements in listElems
are square and symmetric matrices. If the block is a diagonal matrix, theFunctionImLookingFor
should return a list element for each diagonal element.
However, the function should be able to deal with building block matrices like
[,1] [,2] [,3]
[1,] 1 1 0
[2,] 1 1 1
[3,] 0 1 1
or
[,1] [,2] [,3]
[1,] 1 0 1
[2,] 0 1 1
[3,] 1 1 1
i.e. deal with zeros in blocks, which are not diagonal matrices.
回答1:
I hope this will work for all your cases, the test at the bottom includes a block that contains zeroes.
theFunctionImLookingFor <- function(mat, plot.graph = FALSE) {
stopifnot(nrow(mat) == ncol(mat))
x <- mat
diag(x) <- 1
edges <- as.matrix(summary(x)[c("i", "j")])
library(igraph)
g <- graph.edgelist(edges, directed = FALSE)
if (plot.graph) plot(g)
groups <- unique(Map(sort, neighborhood(g, nrow(mat))))
sub.Mat <- Map(`[`, list(mat), groups, groups, drop = FALSE)
sub.mat <- Map(as.matrix, sub.Mat)
return(sub.mat)
}
listElems <- list(matrix(1:4,ncol=2,nrow=2),
matrix(5:8,ncol=2,nrow=2),
matrix(c(0, 1, 0, 0, 0, 1, 0, 0, 1),ncol=3,nrow=3),
matrix(1:1,ncol=1, nrow=1))
mat <- bdiag(listElems)
theFunctionImLookingFor(mat, plot.graph = TRUE)
# [[1]]
# [,1] [,2]
# [1,] 1 3
# [2,] 2 4
# [[2]]
# [,1] [,2]
# [1,] 5 7
# [2,] 6 8
# [[3]]
# [,1] [,2] [,3]
# [1,] 0 0 0
# [2,] 1 0 0
# [3,] 0 1 1
# [[4]]
# [,1]
# [1,] 1

来源:https://stackoverflow.com/questions/26773290/r-is-there-a-simple-and-efficient-way-to-get-back-the-list-of-building-block-ma