我正在编写一个脚本来可视化大型网络中的社区。我想根据节点的社区成员资格在图表中选择边缘,然后更改其颜色属性。
例如,我可以构造一个图形并为节点赋予如下唯一的名称:
library(igraph)
library(random)
g <- barabasi.game(100)
V(g)$name <- randomStrings(100,len=2,digits=FALSE,loweralpha=FALSE)
wt <- walktrap.community(g)
然后选择一个社区来可视化并创建一个诱导子图:
v3 <- V(g)[membership(wt)==3]
g3 <- induced.subgraph(g,v3)
我发现获得匹配边缘的最佳方式是:
matching_edge <- function(g1,e,g2) {
# given an edge e in g1, return the corresponding edge in g2
name1 <- V(g1)[get.edges(g1,e)[1,1]]$name
name2 <- V(g1)[get.edges(g1,e)[1,2]]$name
E(g2)[get.edge.ids(g2,c(name1,name2))]
}
E(g)$color = 'gray'
for (e in E(g3)) {
eg <- matching_edge(g3,e,g)
E(g)[eg]$color <- 'red'
}
最后,我的情节:
plot(g,
vertex.label=NA,
vertex.shape="none",
vertex.size=0,
edge.arrow.mode=0,
edge.width=1)
这样可以正常工作,但是matching_edge()
的循环使用几千个节点的大图来缓慢地痛苦。似乎应该有更好的方法来做到这一点,但我不知道它是什么。
有什么想法吗?
答案 0 :(得分:1)
您无需为此生成子图。
构建图表:
library(igraph)
g <- barabasi.game(100)
wt <- walktrap.community(g)
根据源节点的社区制作颜色数组并将其分配到边缘:
linkcolors<-rainbow(max(wt$membership))
E(g)$color <- linkcolors[membership(wt)[tail_of(g,E(g))]]
情节:
plot(g,
vertex.label=NA,
vertex.shape="none",
vertex.size=0,
edge.arrow.mode=0,
edge.width=1)
这是解决方案的更长,一步一步的版本:
# the largest membership id equals the number of communities
numberofcommunities<- max(wt$membership)
# array of as many colours as there are communities
linkcolors<-rainbow(numberofcommunities)
# array with the source vertex of each edge
sourcenodes<-tail_of(g,E(g))
# array with community of the source vertex of each edge
linkmemberships<- membership(wt)[sourcenodes]
# array with colours corresponding to the
# community of the source vertex of each edge
linkcolors <- linkcolors[linkmemberships]
E(g)$color <- linkcolors
如果您想使用目标节点的社区,请使用head_of()而不是tail_of()。
要仅对同一社区中源节点和目标节点的边缘着色,并以不同方式处理社区之间的边缘(例如,对于无向图),请在绘图前添加:
# get edges between communities:
between_communities_edges<-which(membership(wt)[tail_of(g,E(g))]!=membership(wt)[head_of(g,E(g))])
# do something with them:
E(g)[between_communities_edges]$color='grey95'