如何在 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)
我有一个包含 <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)