Search code examples
pythonnetworkxgraphviz

Set edge lengths according to weights in graphviz_layout


I'm trying to use networkx to plot a weighted graph. I'm generating the positions of vertices using graphviz_layout. I want the edge lengths in the plot to be proportional to the edge weights I am using. Following is my code snippet to achieve this:

import networkx as nx
from networkx.drawing.nx_agraph import graphviz_layout

G = nx.Graph()
G.add_weighted_edges_from(edgelist)
pos = graphviz_layout(G)
nx.draw_networkx(G, pos=pos)

This does not seem to impact edge lengths in the plot. I have seen this post however it only describes how to pass a single default weight for all edges to graphviz_layout (or perhaps I haven't understood the solution).

How may I change my snippet to plot a graph with lengths proportional to edge weights?

In the code snippet above, edgelist is a list of lists of this format:

edgelist = [[4, 219, 1.414], [4, 7, 3.86]]

Solution

  • The key is to set the len attribute of the edges, as described in the Graphviz docs (and available for Neato). Note that this is a preferred edge length, so you will not have complete control. For example, you can add a single weighted edge (u, v, w) to a graph G like so:

    G.add_edge(u, v, len=w)
    

    Here is a full example using the Florentine families graph:

    # Load modules
    import networkx as nx
    from networkx.drawing.nx_agraph import graphviz_layout
    import matplotlib.pyplot as plt
    
    # Construct the graph, choosing some edges to be longer
    G = nx.generators.social.florentine_families_graph()
    lengths = dict()
    long_edges = { frozenset(['Salviati', 'Pazzi']),
                   frozenset(['Ginori', 'Albizzi']) }
    for edge in G.edges():
        if frozenset(edge) in long_edges:
            lengths[edge] = dict(len=2)
        else:
            lengths[edge] = dict(len=1)
    
    nx.set_edge_attributes(G, lengths)
    
    # Plot and show
    pos = graphviz_layout(G, prog='neato')
    nx.draw_networkx(G, pos=pos)
    
    plt.tight_layout()
    plt.show()
    

    To illustrate the difference in layouts when using edge lengths, here is the result where I set two edges of degree one nodes ("Ginori" and "Pazzi") to be longer: Florentine with some longer edges

    And here is the result not using any edge lengths: Florentine with all edges lengths the same