如何在 igraph & R 中创建极地网络图(多环)

How to create a polar network graph (multiple rings) in igraph & R

我有一个包含 <100 个节点和多个类别的图表。我希望属于一个类别的节点位于中心,其他节点在外面均匀排列成一个圆圈 - 就像星图一样,但中心有多个节点。 NodeXL 称其为极坐标图(参见:http://www.connectedaction.net/2013/03/03/how-to-plot-a-network-in-a-polar-layout-using-nodexl/) 鉴于来自数据框图表的手册中的数据:

actors<-data.frame(name=c("Alice", "Bob", "Cecil", "David",
                        "Esmeralda"),
                 age=c(48,33,45,34,21),
                 gender=c("F","M","F","M","F"))
relations <- data.frame(from=c("Bob", "Cecil", "Cecil", "David",
                           "David", "Esmeralda"),
                    to=c("Alice", "Bob", "Alice", "Alice", "Bob", "Alice"),
                    same.dept=c(FALSE,FALSE,TRUE,FALSE,FALSE,TRUE),
                    friendship=c(4,5,5,2,1,1), advice=c(4,5,5,4,2,3))
g <- graph.data.frame(relations, directed=TRUE, vertices=actors)

如果我想让雌性居中,雄性围成一圈怎么办? 我可以将图表和图表分别分开,但我无法思考如何将它们重新组合在一起,正在寻找另一个答案。

gsubf<-induced.subgraph(g,V(g)$gender=="F")
gsubm<-induced.subgraph(g,V(g)$gender=="M")
gsubfcoords<-layout.fruchterman.reingold(gsubf, xlim=c(-2,2), ylim=c(-2,2))
gsubmcoords<-layout.circle(gsubm)

然后我可以将它们分配给 V(gsubf)$x、V(gsubf)$y...但我正在努力如何将它们重新组合在一起。可能有更简单的方法?或者可能是另一个做极地的包裹?

我最近在邮件列表上回复了这个问题,但为了完整起见,我也会在这里包含答案。

igraph 布局是简单的矩阵,每个顶点有 2 列和一行, 所以最简单的可能是你自己生成这样一个矩阵。如果你想 以 alpha 角(在 弧度),那么你必须使用以下公式计算出 X 和 Y坐标:

X = r * cos(alpha)
Y = -r * sin(alpha)

其中Y坐标取反只是因为坐标的Y轴 屏幕的系统是从上到下的。所以你可以在 R:

中创建这样的函数
polar.layout <- function(radii, angles) {
    cbind(radii*cos(angles), -radii*sin(angles))        
}

必须使用两个列表调用 polar.layout 函数:一个指定 每个顶点的半径和一个指定每个顶点的角度的半径。它 然后将 return 一个可以传递给 plot() 的矩阵对象,如下所示:

layout <- polar.layout(radii, angles)
plot(graph, layout=layout)

所以您只需要两个向量:一个用于半径,一个用于角度。您可以按以下方式从性别构建这些:

males <- which(V(g)$gender == "M")
females <- which(V(g)$gender == "F")
radii <- ifelse(V(g)$gender == "F", 1, 2)
angles <- rep.int(0, vcount(g))
angles[males] <- (1:length(males)-1) * 2 * pi / length(males)
angles[females] <- (1:length(females)-1) * 2 * pi / length(females)
layout <- polar.layout(radii, angles)
plot(g, layout=layout)