Is it possible to draw a graph with multiple color for each node with networkx

|▌冷眼眸甩不掉的悲伤 提交于 2020-06-28 01:54:43

问题


I want to color nodes and edges of Karate club graph. But some of nodes have more than one color. Is there any way to color a node with more than one color in python (especially with networkx)? I need something like this:


回答1:


This can be done but it will probably require a lot of work to obtain the exact result you want. You could start with networkx and pygraphviz like this:

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 makes use of graphviz which has really a lot of options. Most of them can be set either for individual nodes (or edges) or globally for all of them like in the example above. It is all well explained in the graphviz documentation.

The above snippet only shows how to make the nodes filled half with one color and half with the other. See the result below (not very beautiful, I know).

EDIT

Hmm, so this kinda grew on me, and I really wanted to make something more similar to what you posted. This is what I came up with:

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

The program definitely can be improved, and I'm still not very happy with the results but maybe you'll find it helpful.




回答2:


setting attribute 'style' to 'filled' is not work. change it to 'wedged' will be fine.

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


来源:https://stackoverflow.com/questions/49587251/is-it-possible-to-draw-a-graph-with-multiple-color-for-each-node-with-networkx

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!