Python 如何使用networkx绘制社区

Python 如何使用networkx绘制社区,python,graph,networkx,Python,Graph,Networkx,如何使用python networkx绘制社区图,如下图所示: 有关networkx.draw\u networkx\u节点和networkx.draw\u networkx\u边的文档说明了如何设置节点和边的颜色。可以通过查找每个社区的节点位置,然后绘制包含所有位置(以及部分位置)的面片(例如,matplotlib.patches.Circle)来创建社区边界面片 难点在于图形布局/设置节点位置。 顺便说一句,networkx中没有实现“开箱即用”所需图形布局的例程。您希望执行以下操作: 相

如何使用python networkx绘制社区图,如下图所示:


有关
networkx.draw\u networkx\u节点和
networkx.draw\u networkx\u边的文档说明了如何设置节点和边的颜色。可以通过查找每个社区的节点位置,然后绘制包含所有位置(以及部分位置)的面片(例如,
matplotlib.patches.Circle
)来创建社区边界面片

难点在于图形布局/设置节点位置。 顺便说一句,networkx中没有实现“开箱即用”所需图形布局的例程。您希望执行以下操作:

  • 相对于彼此定位社区:创建一个新的加权图,其中每个节点对应一个社区,权重对应于社区之间的边数。使用您喜爱的图形布局算法(例如,
    spring\u布局
    )获得一个像样的布局

  • 在每个社区中定位节点:为每个社区创建一个新的图形。查找子图的布局

  • 组合1)和3)中的节点位置。例如,按1)中的系数10计算社区职位;将这些值添加到该社区中所有节点的位置(如2中计算的)

  • 我一直想实现这一点有一段时间了。我可能今天晚些时候或者周末做

    编辑: 瞧。现在,您只需要在节点周围(后面)绘制您最喜欢的补丁

    补遗 虽然总体思路是合理的,但我上面的旧实现存在一些问题。最重要的是,对于规模不均的社区,实施效果并不理想。具体来说,
    \u position\u communities
    在画布上为每个社区提供相同数量的不动产。如果一些社区比其他社区大得多,那么这些社区最终会被压缩到与小社区相同的空间中。显然,这并不能很好地反映图形的结构

    我写了一个可视化网络的库,叫做。它包括上述社区布局例程的改进版本,在安排社区时还考虑了社区的大小。它与
    networkx
    igraph
    图形对象完全兼容,因此制作美观的图形应该简单快捷(至少是这样)


    哇!这是个好主意。感谢您的实施倒数第二行需要是
    nx.draw(g,pos,node_color=list(partition.values())
    @mortezashahrarinia谢谢您的提醒。显然,他们改变了
    分区的类型。现在变了。
    
    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
    
    import matplotlib.pyplot as plt
    import networkx as nx
    
    # installation easiest via pip:
    # pip install netgraph
    from netgraph import Graph
    
    # create a modular graph
    partition_sizes = [10, 20, 30, 40]
    g = nx.random_partition_graph(partition_sizes, 0.5, 0.1)
    
    # since we created the graph, we know the best partition:
    node_to_community = dict()
    node = 0
    for community_id, size in enumerate(partition_sizes):
        for _ in range(size):
            node_to_community[node] = community_id
            node += 1
    
    # # alternatively, we can infer the best partition using Louvain:
    # from community import community_louvain
    # node_to_community = community_louvain.best_partition(g)
    
    community_to_color = {
        0 : 'tab:blue',
        1 : 'tab:orange',
        2 : 'tab:green',
        3 : 'tab:red',
    }
    node_color = {node: community_to_color[community_id] for node, community_id in node_to_community.items()}
    
    Graph(g,
          node_color=node_color, node_edge_width=0, edge_alpha=0.1,
          node_layout='community', node_layout_kwargs=dict(node_to_community=node_to_community),
          edge_layout='bundled', edge_layout_kwargs=dict(k=2000),
    )
    
    plt.show()