'PyVis: visually cluster based on edge weight

I am trying to visually cluster nodes in a network based on the weight of their edges: nodes with high edge weight should be close by in the 2d Euclidean space of the output image.

I built my network with NetworkX and converted it to PyVis in order to display it. I'm wondering if there's a way to set up PyVis so that nodes with high weight edges between them are close by, ideally I would love it to look like this example.

I'm also wondering if instead I should pre-emptively cluster the nodes in NetworkX, tag them, and then use this information to display them close by (for clustering see this answer).

Another alternative would be to remove all edges except for those with high relative value (0.0075 in my example below), but I don't know if this would help with getting PyVis to visually cluster the nodes together.

Or are there any other alternatives to obtain something nice (PageRank, etc)? There seems to be a dearth of information on how to properly visualise graph data (I haven't found much apart from this).

enter image description here

Here's a MWE to reproduce what I'm seeing; basically, in this minimal example, I would like to see nodes [7,9,16,51,57] be clustered close together, compared to the other nodes (ideally I would love it to look like this example - I can always figure out the colouring later on):

def draw_graph3( networkx_graph, notebook=True, output_filename='graph.html', open_output=False,
                 show_buttons=False, only_physics_buttons=False ):
    # import
    from pyvis import network as net
    
    # make a pyvis network
    pyvis_graph = net.Network( notebook=notebook )
    pyvis_graph.width = '1000px'
    # for each node and its attributes in the networkx graph
    for node, node_attrs in networkx_graph.nodes( data=True ):
        pyvis_graph.add_node( node, **node_attrs )
    #         print(node,node_attrs)
    
    # for each edge and its attributes in the networkx graph
    for source, target, edge_attrs in networkx_graph.edges( data=True ):
        # if value/width not specified directly, and weight is specified, set 'value' to 'weight'
        if not 'value' in edge_attrs and not 'width' in edge_attrs and 'weight' in edge_attrs:
            # place at key 'value' the weight of the edge
            edge_attrs[ 'value' ] = edge_attrs[ 'weight' ]
        # add the edge
        pyvis_graph.add_edge( source, target, **edge_attrs )
    
    # turn buttons on
    if show_buttons:
        if only_physics_buttons:
            pyvis_graph.show_buttons( filter_=[ 'physics' ] )
        else:
            pyvis_graph.show_buttons()
    
    # return and also save
    pyvis_graph.show( output_filename )
    
    if open_output:
        import webbrowser
        import os
        
        webbrowser.open( f'file://{os.getcwd()}/{output_filename}' )


# Build NetworkX graph
import networkx as nx

pre_neurons = [7, 9, 16, 51, 57, 114, 122, 126, 129, 138, 170, 202, 208, 221, 254]
post_neurons = [7, 9, 16, 51, 57, 114, 122, 126, 129, 138, 170, 202, 208, 221, 254]
edges_pre = [7, 7, 7, 9, 9, 9, 9, 9, 16, 16, 16, 16, 16, 16, 16, 16, 16, 51, 51, 51, 51, 51, 51, 57, 57, 57, 57, 57, 57, 114, 114, 114, 114, 114, 114, 114, 114, 122, 122, 122, 126, 126, 126, 126, 126, 126, 129, 129, 129, 129, 129, 138, 138, 138, 138, 138, 138, 170, 170, 170, 170, 170, 170, 202, 202, 202, 202, 202, 202, 202, 208, 208, 208, 208, 208, 208, 221, 221, 254, 254, 254, 254, 254, 254, 254, 254]
edges_post = [122, 129, 170, 51, 122, 129, 138, 208, 7, 9, 51, 57, 114, 129, 170, 208, 221, 9, 129, 170, 202, 221, 254, 114, 129, 170, 202, 208, 254, 51, 122, 126, 129, 138, 202, 208, 254, 114, 202, 208, 9, 51, 122, 202, 221, 254, 51, 114, 126, 138, 170, 7, 57, 114, 126, 129, 170, 7, 9, 57, 126, 138, 221, 51, 114, 126, 129, 170, 208, 221, 7, 51, 138, 170, 202, 254, 51, 170, 9, 16, 57, 114, 122, 126, 138, 170]
edges_weights = [0.0, 0.0, 0.0, 0.0075, 0.0, 0.0, 0.0, 0.0, 0.0075, 0.0075, 0.0075, 0.0075, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0075, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0, 0.0, 0.0005, 0.0005, 0.0005, 0.0005, 0.0, 0.0005, 0.0005, 0.0005, 0.0005, 0.0, 0.0, 0.0005, 0.0005, 0.0005, 0.0005, 0.0, 0.0, 0.0, 0.0005, 0.0005, 0.0005, 0.0, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005, 0.0, 0.0, 0.0005, 0.0005, 0.0005, 0.0005, 0.0, 0.0005, 0.0, 0.0, 0.0, 0.0005, 0.0005, 0.0005, 0.0005, 0.0005]

g = nx.Graph()
g.add_nodes_from( pre_neurons )
g.add_nodes_from( post_neurons )
for i, j, w in zip( edges_pre, edges_post, edges_weights ):
    g.add_edge( i, j, weight=w )

a = draw_graph3( g, output_filename='test.html', open_output=True, notebook=False, show_buttons=True,
                 only_physics_buttons=True )


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source