Search code examples
pythonmatplotlibnodesnetworkxedges

How can I assign different colors to different nodes in my network?


I tried everything I could find online but still kept coming up short. My goal is to use matplotlib/networkx to color nodes distinctly based on their identifier.

So I currently have the edges and the nodes of my graph (here's a small snippet of each):

sub_interactome.edges = [('P30876', 'P36954'), ('P30876', 'P19387'), ('P41136', 'Q60722'), ('P41136', 'P17433')]

sub_interactome.nodes = ['P30876', 'P36954', 'P41136', 'Q60722', 'P30876', 'P19387','P17433']

I'm trying to make a distinct color for each node for my end graph. So far, this is the code that I made but I'm sure that I'm far off. This part gets me the network itself.

plt.figure(figsize=(10,10))
nx.spring_layout(sub_interactome)
nx.draw_networkx(sub_interactome, with_labels=True)
col.Colormap(valid_uniprots, len(valid_uniprots))
plt.tick_params(axis='x', which='both', bottom=False, top=False, labelbottom=False)
plt.tick_params(axis='y', which='both', right=False, left=False, labelleft=False)
for ty in ['right','top','bottom','left']:
    plt.gca().spines[ty].set_visible(False)   
plt.show()

I have 239 total nodes so just typing in a color for each obviously wouldn't work. I tried to create a colormap using various methods I could find online but that didn't work. I then turned it all into a dictionary to try to map the color map that way:

def Convert(tup, di): 
    for a, b in tup: 
        di.setdefault(a, [] ).append(b) 
    return di 
dictionary = {}
keyvalinteractome = Convert(sub_interactome.edges,dictionary)

This made me a dictionary but I still couldn't figure out a proper way to color each node. I probably don't need this since I can just create a nodes list using .nodes but I figured maybe it could help in some way. My latest attempt to create the color map for these is below:

G = sub_interactome
n_colors = len(keyvalinteractome.keys())

pos = nx.spring_layout(G)
for key in G.nodes():
    nx.draw_networkx_nodes(G,pos,[m for m in G.nodes() if keyvalinteractome[m]==key],node_color=['red','blue','green','yellow','purple'])
    nx.draw_networkx_edges(G,pos)

This way, I still have to input the colors which isn't going to work and it gives me an error anyways.

I'd really appreciate if anyone could help me out with this, I'm new to python and trying to learn but I've been trying to do this one issue for about 5 hours now.

Thanks in advance!


Solution

  • If I am not wrong you are looking for some kinda color generator. I have been through similar challenges plus I had a challenge to pick most contrasting colors.

    Following piece of code should work just fine for you, it uses HSV color technique and chooses colors from 360 degree Hue color cylinder:

    import numpy as np, colorsys
    
    def choose_colors(node_list):
    
        num_colors = len(node_list)
        
        colors=[]
        for i in np.arange(0., 360., 360. / num_colors):
            hue = i/360.
            lightness = (30 + np.random.rand() * 70)/100.0
            saturation = (30 + np.random.rand() * 70)/100.0
            colors.append(colorsys.hls_to_rgb(hue, lightness, saturation))
        return colors
    
    

    This snippet returns an array of color same as length of node_list passed to it.