问题描述
如何使用python networkx这样的图绘制社区图:
How can I draw a graph with it's communities using python networkx like this image :
推荐答案
networkx.draw_networkx_nodes
和networkx.draw_networkx_edges
的文档介绍了如何设置节点和边缘颜色.可以通过找到每个社区的节点位置,然后绘制包含所有位置(然后是某些位置)的补丁(例如matplotlib.patches.Circle
)来制作包围社区的补丁.
The documentation for networkx.draw_networkx_nodes
and networkx.draw_networkx_edges
explains how to set the node and edge colors. The patches bounding the communities can be made by finding the positions of the nodes for each community and then drawing a patch (e.g. matplotlib.patches.Circle
) that contains all positions (and then some).
最困难的是图形布局/设置节点位置.AFAIK,networkx中没有例程可以开箱即用"地实现所需的图形布局.您要执行的操作如下:
The hard bit is the graph layout / setting the node positions.AFAIK, there is no routine in networkx to achieve the desired graph layout "out of the box". What you want to do is the following:
1)相对于社区定位社区:创建一个新的加权图,其中每个节点对应一个社区,权重对应于社区之间的边数.使用您最喜欢的图形布局算法(例如spring_layout
)获得一个体面的布局.
1) Position the communities with respect to each other: create a new, weighted graph, where each node corresponds to a community, and the weights correspond to the number of edges between communities. Get a decent layout with your favourite graph layout algorithm (e.g.spring_layout
).
2)将节点放置在每个社区中:为每个社区创建一个新图.查找子图的布局.
2) Position the nodes within each community: for each community, create a new graph. Find a layout for the subgraph.
3)合并1)和3)中的节点位置.例如.将1)中计算出的社区职位规模扩大10倍;将这些值添加到该社区内所有节点的位置(按2计算).
3) Combine node positions in 1) and 3). E.g. scale community positions calculated in 1) by a factor of 10; add those values to the positions of all nodes (as computed in 2)) within that community.
Voila.现在,您只需要在节点周围(后面)绘制自己喜欢的补丁.
Voila. Now you just need to draw your favourite patch around (behind) the nodes.
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
def community_layout(g, partition):
"""
Compute the layout for a modular graph.
Arguments:
----------
g -- networkx.Graph or networkx.DiGraph instance
graph to plot
partition -- dict mapping int node -> int community
graph partitions
Returns:
--------
pos -- dict mapping int node -> (float x, float y)
node positions
"""
pos_communities = _position_communities(g, partition, scale=3.)
pos_nodes = _position_nodes(g, partition, scale=1.)
# combine positions
pos = dict()
for node in g.nodes():
pos[node] = pos_communities[node] + pos_nodes[node]
return pos
def _position_communities(g, partition, **kwargs):
# create a weighted graph, in which each node corresponds to a community,
# and each edge weight to the number of edges between communities
between_community_edges = _find_between_community_edges(g, partition)
communities = set(partition.values())
hypergraph = nx.DiGraph()
hypergraph.add_nodes_from(communities)
for (ci, cj), edges in between_community_edges.items():
hypergraph.add_edge(ci, cj, weight=len(edges))
# find layout for communities
pos_communities = nx.spring_layout(hypergraph, **kwargs)
# set node positions to position of community
pos = dict()
for node, community in partition.items():
pos[node] = pos_communities[community]
return pos
def _find_between_community_edges(g, partition):
edges = dict()
for (ni, nj) in g.edges():
ci = partition[ni]
cj = partition[nj]
if ci != cj:
try:
edges[(ci, cj)] += [(ni, nj)]
except KeyError:
edges[(ci, cj)] = [(ni, nj)]
return edges
def _position_nodes(g, partition, **kwargs):
"""
Positions nodes within communities.
"""
communities = dict()
for node, community in partition.items():
try:
communities[community] += [node]
except KeyError:
communities[community] = [node]
pos = dict()
for ci, nodes in communities.items():
subgraph = g.subgraph(nodes)
pos_subgraph = nx.spring_layout(subgraph, **kwargs)
pos.update(pos_subgraph)
return pos
def test():
# to install networkx 2.0 compatible version of python-louvain use:
# pip install -U git+https://github.com/taynaud/python-louvain.git@networkx2
from community import community_louvain
g = nx.karate_club_graph()
partition = community_louvain.best_partition(g)
pos = community_layout(g, partition)
nx.draw(g, pos, node_color=list(partition.values())); plt.show()
return
这篇关于如何使用networkx绘制社区的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!