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

主宰稳场 提交于 2021-02-08 02:56:06

问题


I have a graph with <100 nodes, with several categories. I would like the nodes belonging to one category to be in the center, with the other nodes arranged evenly in a circle around the outside - like a star graph, but with multiple nodes in the center. NodeXL calls this a polar graph (see: http://www.connectedaction.net/2013/03/03/how-to-plot-a-network-in-a-polar-layout-using-nodexl/) Given this data from the manual for graphs from dataframes:

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)

What if I want the females in the center and the males arranged in a circle around? I can divide up the graph and graph each separately, but I'm having trouble thinking through how to put them back together and am looking for another answer.

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)

Then I could assign them to V(gsubf)$x, V(gsubf)$y... but I'm struggling how to put it all back together. There may be an easier way? or maybe another package to do polar?


回答1:


I have responded to this question on the mailing list recently, but for sake of completeness I'll also include the answer here.

igraph layouts are simply matrices with 2 columns and one row for each vertex, so the easiest is probably if you generate such a matrix yourself. If you want to place a vertex at radius r from the center with an angle of alpha (in radians), then you have to use the following formulae to figure out the X and Y coordinates:

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

where the Y coordinate is negated only because the Y axis of the coordinate system of the screen is oriented from top to bottom. So you can create a function like this in R:

polar.layout <- function(radii, angles) {
    cbind(radii*cos(angles), -radii*sin(angles))        
}

The polar.layout function has to be called with two lists: one that specifies the radius of each vertex and one that specifies the angle of each vertex. It will then return a matrix object that can be passed to plot() as follows:

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

So all you need is two vectors: one for the radii and one for the angles. You can construct these from the genders as follows:

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)


来源:https://stackoverflow.com/questions/28868214/how-to-create-a-polar-network-graph-multiple-rings-in-igraph-r

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!