Passing in a list of colours (one for each node in a graph plot)

I have a plot which takes a networkx graph as well as a node attribute which the code uses to identify the node ‘type’. I then create a list of colours - one for each node/marker. The colour relates to the node type.

When I pass the list of colours in to the plotly dictionary it’s showing each node as dark/black. How should I change this?

# Function to plot a networkx graph requires the pandas dataframe, pos (dict) and title (str)
# pos is created such as: pos = nx.spring_layout(my_test_graph)

def plot_graph(graph, pos, title='Default', node_type=None):
    import seaborn as sns
    from plotly.offline import iplot
    from plotly.offline import init_notebook_mode
    import itertools
    init_notebook_mode(connected=False)
    
    # Build the list of node colours
    palette = itertools.cycle(sns.color_palette())
    default_colour = next(palette)
    types_list = []

    for node in graph.nodes:
        type_value = (graph.nodes[node].get(node_type))
        if type_value is not None and type_value not in types_list:
            types_list.append(graph.nodes[node].get(node_type))
    
    type_colour = {}
    for node_type_value in types_list:
        type_colour[node_type_value] = next(palette)

    master_colours = []
    for node in graph.nodes:
        # Check if the node has a key which exists in our type_attributes
        if node_type in graph.nodes[node].keys():
            master_colours.append(type_colour[graph.nodes[node][node_type]])
        else:
            master_colours.append(default_colour)
    print('Master colours: ')
    print(master_colours)
    
      
    #Define the lists of node coordinates:
    Xn = [pos[key][0] for key in pos]
    Yn = [pos[key][1] for key in pos]

    # Define the lists of node coordinates:
    trace_nodes=dict(type='scatter',
                     x=Xn, 
                     y=Yn,
                     mode='markers+text',
                     text= list(pos.keys()),
                     marker=dict(size=30, color=master_colours),
                     hoverinfo='text')


    # Record the coordinates of edge ends:
    Xe=[]
    Ye=[]
    for e in graph.edges():
        Xe.extend([pos[e[0]][0], pos[e[1]][0], None])
        Ye.extend([pos[e[0]][1], pos[e[1]][1], None])

    # The trace_edges defines the graph edges as a Plotly trace of type scatter, mode lines. 
    # After the x-coordinates, respectively y-coordinates of the ends of an edge is inserted None, 
    # because otherwise, "the tracer" joins all edges.
    
    edges_list =  [dict(type='scatter',
                   x=[pos[e[0]][0], pos[e[1]][0], None],
                   y=[pos[e[0]][1], pos[e[1]][1], None],
                   mode='lines',
                   line=dict(width=e[2]['weight'], color='rgb(25,25,25)')) for e in graph.edges(data=True)]

  
    Xe=[]
    Ye=[]


    # Plotly layout:
    # To get a good looking graph it is recommended to define data as a list having the first element 
    # the trace corresponding to edges, and the second the trace for nodes. Otherwise the lines will 
    # be traced over the node dots.
    axis=dict(showline=False, # hide axis line, grid, ticklabels and  title
              zeroline=False,
              showgrid=False,
              showticklabels=False,
              title='' 
              )
    layout=dict(title=title,  
                font= dict(family='Balto'),
                width=900,
                height=900,
                autosize=True,
                showlegend=False,
                xaxis=axis,
                yaxis=axis,
                margin=dict(
                l=40,
                r=40,
                b=85,
                t=100,
                pad=0,

        ),
        hovermode='closest',
        plot_bgcolor='#efecea', #set background color            
        )
    print(trace_nodes)
    fig = dict(data=edges_list+[trace_nodes], layout=layout)
    #iplot(fig)
    iplot(fig, show_link=False, config={'modeBarButtonsToRemove': ['sendDataToCloud']})

The output that I get (from print statements) is:

Master colours: 
[(1.0, 0.4980392156862745, 0.054901960784313725), (0.12156862745098039, 0.4666666666666667, 0.7058823529411765), (0.17254901960784313, 0.6274509803921569, 0.17254901960784313), (0.12156862745098039, 0.4666666666666667, 0.7058823529411765), (0.12156862745098039, 0.4666666666666667, 0.7058823529411765), (0.12156862745098039, 0.4666666666666667, 0.7058823529411765)]

{'type': 'scatter', 'x': [-0.19108136860258823, -0.1533263199061208, -0.39012398718790614, -0.264861402183546, 0.9999999999999999, -0.0006069221198387378], 'y': [-0.033908275406154376, -0.19956791620125605, 0.07448031526350267, 0.17943535043110934, 0.13239313567208194, -0.15283260975928353], 'mode': 'markers+text', 'text': ['John', 'Arnold', 'Sarah', 'Samira', 'Bob', 'Grace'], 'marker': {'size': 30, 'color': [
(1.0, 0.4980392156862745, 0.054901960784313725), 
(0.12156862745098039, 0.4666666666666667, 0.7058823529411765), 
(0.17254901960784313, 0.6274509803921569, 0.17254901960784313), 
(0.12156862745098039, 0.4666666666666667, 0.7058823529411765), 
(0.12156862745098039, 0.4666666666666667, 0.7058823529411765), 
(0.12156862745098039, 0.4666666666666667, 0.7058823529411765)]}, 'hoverinfo': 'text'}

How should I restructure this so that nodes are coloured according to their ‘node_type’ rathe than just dark?

@laurie Plotly doesn’t work with color codes as tuples of elements in [0,1]. A color should be given either
as a string, 'rgb(125, 57, 230)', or in hex-format, '#5fa023'.

Hence after seting up your 'master_colours' list, convert the color codes to rgb format:

master_colours  = [f'rgb{tuple((np.array(color)*255).astype(np.uint8))}' for color in master_colours]
1 Like