【问题标题】:Is it possible to draw a graph with multiple color for each node with networkx是否可以使用networkx为每个节点绘制具有多种颜色的图形
【发布时间】:2018-03-31 11:31:30
【问题描述】:

我想为空手道俱乐部图的节点和边缘着色。但是有些节点有不止一种颜色。有没有办法在python中用一种以上的颜色为节点着色(尤其是networkx)? 我需要这样的东西:

【问题讨论】:

    标签: python graph networkx


    【解决方案1】:

    这可以做到,但可能需要大量工作才能获得您想要的确切结果。你可以像这样从networkx and pygraphviz 开始:

    import networkx as nx
    
    karate = nx.generators.social.karate_club_graph()                        
    karate_agr = nx.nx_agraph.to_agraph(karate)
    
    karate_agr.node_attr['style'] = 'filled'
    karate_agr.node_attr['shape'] = 'circle'
    karate_agr.node_attr['gradientangle'] = 90
    
    for i in karate_agr.nodes():
        n = karate_agr.get_node(i)
        n.attr['fillcolor'] = 'green;0.5:yellow'
    
    karate_agr.draw('karate.png',prog='dot')
    

    Pygraphviz 使用graphviz,它有很多选择。它们中的大多数可以为单个节点(或边缘)设置,也可以为所有它们全局设置,如上面的示例所示。这在graphviz documentation中都有很好的解释。

    上面的 sn-p 只显示了如何使节点用一种颜色填充一半,用另一种颜色填充一半。看看下面的结果(不是很漂亮,我知道)。

    编辑

    嗯,所以这有点在我身上长大,我真的很想做一些与您发布的内容更相似的东西。这是我想出的:

    # coding: utf-8
    import networkx as nx
    import itertools
    from collections import Counter
    
    
    def edge_in_com(nodes, graph):
        edges = []
        for (i, j) in itertools.combinations(nodes, 2):
            if (i, j) in graph.edges():
                edges.append((i, j))
        return edges
    
    
    karate = nx.generators.social.karate_club_graph()
    karate_agr = nx.nx_agraph.to_agraph(karate)
    
    karate_agr.graph_attr['dpi'] = 180
    karate_agr.edge_attr.update(
        dir='both', arrowhead='inv', arrowtail='inv', penwidth=2.0)
    
    karate_agr.node_attr.update(
        style='filled',
        fontcolor='white',
        shape='circle',
        color='transparent',
        gradientangle=90)
    
    colors = ['grey', 'pink', 'blue', 'purple']
    communities = list(nx.community.asyn_fluidc(karate, 4))
    
    most_edges = []
    for n, com in enumerate(communities):
        edges = edge_in_com(com, karate)
        most_edges.extend(edges)
        for edge in edges:
            e = karate_agr.get_edge(*edge)
            e.attr['color'] = colors[n]
        for node in com:
            node = karate_agr.get_node(node)
            node.attr['fillcolor'] = colors[n]
    
    other = [e for e in karate.edges() if e not in most_edges]
    
    for edge in other:
        gn = karate_agr.get_node
        color = gn(edge[0]).attr['fillcolor']
        karate_agr.get_edge(*edge).attr['color'] = color
    
    for n in karate_agr.nodes():
        cls = [e.attr['color'] for e in karate_agr.in_edges(n)]
        cls2 = [e.attr['color'] for e in karate_agr.out_edges(n)]
        cls = set(cls + cls2)
        if len(cls) > 1:
            # if n.attr['fillcolor'] != cls[0]:
            color1 = cls.pop()
            color2 = cls.pop()
            color_mix = ''.join([color1, ';', '0.5:', color2])
            n.attr['fillcolor'] = color_mix
    
    karate_agr.draw('karate.png', prog='neato')
    

    该程序肯定可以改进,我对结果仍然不是很满意,但也许你会发现它有帮助。

    【讨论】:

    • 非常感谢。我花了很长时间安装 pygraphviz。实际上我非常努力地在 windows 上安装 pygraphviz 并且失败了,所以我在 ubuntu 上尝试了它(这很容易没有问题)。非常感谢:)
    • @user137927 不客气。随意接受我的回答:)
    • 对不起,我完全忘记了,谢谢提醒
    • @user137927 真的没问题。我已经修改了我的答案,看看你是否喜欢。
    【解决方案2】:

    将属性“样式”设置为“填充”无效。将其更改为“楔形”就可以了。

    karate_agr.node_attr['style'] = 'wedged'
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-06
      • 1970-01-01
      • 2012-11-11
      • 1970-01-01
      相关资源
      最近更新 更多