Search code examples
pythonnetworkx

Change specific nodes shapes based on a list


Since it is possible to change node color, edgecolor, node size etc of specific nodes within a graph, I was wondering if there's a way to change the shape of specific nodes using a list. I've tried the following code:

node_shape = []  
for node in S:
    if node in nodes_of_interest:
        node_shape.append('d')
    else:
        node_shape.append('o')

nx.draw_networkx(S, pos = layout, font_size = '14', node_color = color_map, edgecolors = edge_colors, node_size = node_size,font_weight='bold', )

However I receive the following error:

ValueError: Unrecognized marker style ['o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'd', 'o', 'o', 'd', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'd', 'o', 'o', 'o', 'o', 'o', 'd', 'd', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'd', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o']

I was wondering if I made a mistake or if this is just not possible. Thanks for all your suggestions in advance!


Solution

  • The nodes are ultimately drawn using matplotlib's scatter. This is from the source code for nx.draw_network_nodes, which is called from within nx.draw_networkx:

    node_collection = ax.scatter(xy[:, 0], xy[:, 1],
                                 s=node_size,
                                 c=node_color,
                                 marker=node_shape,
                                 cmap=cmap,
                                 vmin=vmin,
                                 vmax=vmax,
                                 alpha=alpha,
                                 linewidths=linewidths,
                                 edgecolors=edgecolors,
                                 label=label)
    

    But each call to scatter will only accept one marker for all points being plotted. Therefore, in order to have different markers you will need to make multiple calls to the plotting function -- one for each subset of nodes having the same marker style. Here's a simple working example:

    
        G = nx.Graph(np.array([[0,1,0],[1,0,1],[0,1,0]]))
        layout = nx.layout.spring_layout(G)
        nodes_of_interest = [0,2]
        other_nodes = [1]
        nx.draw_networkx(G,layout,nodelist=nodes_of_interest,node_shape='d')
        nx.draw_networkx(G,layout,nodelist=other_nodes,node_shape='o')
    
    

    PS: for fine-tuning, it is oftentimes helpful to use nx.draw_network_nodes together with nx.draw_network_edges directly, instead of nx.draw_networkx.