是否可以使用networkx为每个节点绘制具有多种颜色的图形

时间:2018-03-31 11:31:31

标签: python graph networkx

我想为空手道俱乐部图表的节点和边缘着色。但是一些节点有多种颜色。有没有办法在python中为多个颜色的节点着色(特别是使用networkx)? 我需要这样的东西:

enter image description here

2 个答案:

答案 0 :(得分:2)

这可以完成,但可能需要大量工作才能获得您想要的确切结果。您可以从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中已经很好地解释了这一点。

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

karateeee, hiyyaaagh

修改

嗯,所以这种情况在我身上有所增长,我真的想做一些与你发布的内容更相似的东西。这就是我想出的:

# 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')

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

karat2

答案 1 :(得分:1)

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

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