如何将图转换为指定类型(非dgCMatrix)的稀疏邻接矩阵?
igraph转换为指定类型稀疏邻接矩阵的解决方案
问题1:如何将图转换为dgCMatrix以外指定类型的稀疏邻接矩阵?
igraph的as_adjacency_matrix()(或简写as_adj())在设置sparse=TRUE时,默认返回dgCMatrix类型的稀疏矩阵。要得到其他稀疏矩阵类型,有两种可行方式:
方式1:先获取dgCMatrix再转换
先通过默认方法得到dgCMatrix,再用Matrix包的as()函数转换为目标类型,比如转换为dgRMatrix(行稀疏矩阵):
library(igraph) library(Matrix) # 创建示例图 g <- make_ring(5) # 获取默认的dgCMatrix adj_c <- as_adjacency_matrix(g, sparse = TRUE) # 转换为dgRMatrix adj_r <- as(adj_c, "RsparseMatrix") class(adj_r) # [1] "dgRMatrix" # attr(,"package") # [1] "Matrix"
方式2:自定义函数直接生成目标类型
如果需要一步生成,可复制igraph内部的get.adjacency.sparse()函数并修改,直接输出指定类型的稀疏矩阵。比如修改后直接返回dgTMatrix:
# 复制并修改igraph的get.adjacency.sparse函数 get_adjacency_dgT <- function(graph, type = c("both", "upper", "lower", "plus"), attr = NULL, edges = TRUE, names = TRUE, binary = FALSE, sparse = TRUE) { type <- match.arg(type) if (!igraph::is_igraph(graph)) { stop("Not a graph object") } n <- igraph::vcount(graph) if (is.null(attr)) { if (edges) { el <- igraph::get.edgelist(graph, names = FALSE) if (type == "upper") { el <- el[el[, 1] < el[, 2], , drop = FALSE] } else if (type == "lower") { el <- el[el[, 1] > el[, 2], , drop = FALSE] } else if (type == "plus") { el <- rbind(el, cbind(el[, 2], el[, 1])) } x <- rep(1, nrow(el)) if (!binary && !igraph::is_directed(graph) && type == "both") { x <- c(x, x) el <- rbind(el, cbind(el[, 2], el[, 1])) } } else { el <- matrix(integer(0), ncol = 2) x <- numeric(0) } } else { el <- igraph::get.edgelist(graph, names = FALSE) x <- igraph::get.edge.attribute(graph, attr) if (!is.numeric(x)) { stop("Edge attribute must be numeric") } if (type == "upper") { keep <- el[, 1] < el[, 2] el <- el[keep, , drop = FALSE] x <- x[keep] } else if (type == "lower") { keep <- el[, 1] > el[, 2] el <- el[keep, , drop = FALSE] x <- x[keep] } else if (type == "plus") { el <- rbind(el, cbind(el[, 2], el[, 1])) x <- c(x, x) } else if (!igraph::is_directed(graph)) { el <- rbind(el, cbind(el[, 2], el[, 1])) x <- c(x, x) } } # 关键修改:直接构造dgTMatrix mat <- Matrix::sparseMatrix(i = el[, 1], j = el[, 2], x = x, dims = c(n, n), giveCsparse = FALSE) if (names) { dn <- list(igraph::V(graph)$name, igraph::V(graph)$name) dimnames(mat) <- dn } mat } # 使用自定义函数一步得到dgTMatrix adj_t <- get_adjacency_dgT(g, type = "both") class(adj_t) # [1] "dgTMatrix" # attr(,"package") # [1] "Matrix"
问题2:如何一步将图转换为稀疏dgTMatrix?
除了上面自定义函数的方式,也可以通过直接构造稀疏矩阵的方式一步实现:
方法1:基于边列表直接构造dgTMatrix
直接从图的边列表出发,用sparseMatrix()函数并指定giveCsparse=FALSE来生成dgTMatrix:
library(igraph) library(Matrix) g <- make_ring(5) # 获取边列表(不含顶点名称) el <- get.edgelist(g, names = FALSE) # 处理无向图的双向边(如果需要type="both") if (!is_directed(g)) { el <- rbind(el, cbind(el[,2], el[,1])) } # 构造dgTMatrix adj_t <- sparseMatrix(i = el[,1], j = el[,2], x = 1, dims = c(vcount(g), vcount(g)), giveCsparse = FALSE) class(adj_t) # [1] "dgTMatrix" # attr(,"package") # [1] "Matrix" # 若需要顶点名称,可添加dimnames dimnames(adj_t) <- list(V(g)$name, V(g)$name)
方法2:使用修改后的自定义函数
即前面问题1中提到的get_adjacency_dgT()函数,调用后可一步得到dgTMatrix,同时支持边属性、类型选择等参数,功能更贴近原生as_adjacency_matrix()。
内容的提问来源于stack exchange,提问作者clp
相关产品推荐
相关产品推荐

