Adnan Ali
Adnan Ali

Reputation: 3055

Set colors to group of nodes by attribute values in Networkx

I have three types of nodes (dynmanicallly drawn hundred or thousands of nodes)

1- Animals 2- Trees 3- Humans

I am reading values from JSON file and dynamically nodes are created with unknown values.

I want to color them by their type. so I assigned a nodetype property to identify.

Here is my node code for nodes.

G.add_node(HumanID, nodetype="red", UserName=userName)
G.add_node(TreeID, nodetype="green", BranchName=branchName)
G.add_node(AnimalID, nodetype="blue", AName=aName)

and to get the values

colors = set(nx.get_node_attributes(G,'nodetype').values())
print(colors)

output: {'green', 'red', 'blue'}

I know this is not right but I want something like this

nx.draw(G,  node_color= colors)

so it should draw nodes with 3 different colors. I tried multiple ways to do so but since I am new with Networkx and Matplotlib so no success.

Upvotes: 2

Views: 2185

Answers (1)

willcrack
willcrack

Reputation: 1852

When coloring graphs using nx.draw it is key to keep the order of colors the same as the nodes order.
So using a set won't do since these are unordered and do not allow duplicate values.

Instead what you want is, from the nx.draw_networkx documentation:

node_color (color or array of colors (default=’#1f78b4’)) – Node color. Can be a single color or a sequence of colors with the same length as nodelist. Color can be string, or rgb (or rgba) tuple of floats from 0-1. If numeric values are specified they will be mapped to colors using the cmap and vmin,vmax parameters. See matplotlib.scatter for more details.

So if we consider a list, we can obtain colors like this:

colors = [u[1] for u in G.nodes(data="nodetype")]

Here is an example:

G=nx.Graph()

G.add_node(1, nodetype="red")
G.add_node(2, nodetype="blue")
G.add_node(3, nodetype="green")
G.add_node(4, nodetype="red")
G.add_edge(1, 3)
G.add_edge(2, 4)
G.add_edge(2, 3)

colors = [u[1] for u in G.nodes(data="nodetype")]
nx.draw(G, with_labels =True, node_color = colors)

Draws:
Example Result


EDIT:

One thing that may cause the issue you're having:

Adding a node with nodetype="not_a_color":

G.add_node(4, nodetype="not_a_color")
colors = [u[1] for u in G.nodes(data="nodetype")]
nx.draw(G, with_labels =True, node_color = colors)

This gives the same error that you're getting:

ValueError: 'c' argument must be a color, a sequence of colors, or a sequence of numbers, not ['red', 'blue', 'green', 'not_a_color']

Of course that if you have a long list it is more difficult to check.
Try running the following, to check if there is a color that is neither "red","green" or "blue"

colors = [u[1] for u in G.nodes(data="nodetype")]

not_colors = [c for c in colors if c not in ("red", "green", "blue")]
if not_colors:
    print("TEST FAILED:", not_colors)

If you have None in any of your node's node_type attribute, this will print those nodes in black:

#(change *colors* to):

colors = []
for u in G.nodes(data="nodetype"):
    if u[1] in ("red", "green", "blue"):
        colors.append(u[1])
    elif u[1] == None:
        colors.append("black")
    else:
        #do something?
        print("ERROR: Should be red, green, blue or None")

Upvotes: 3

Related Questions