2

I'm doing a network visualization using PyVis and was hoping to add some additional items in the tooltip function when hovering on nodes.

I'm basically using the code straight from the tutorial section of the PyVis documentation for the GoT network: https://pyvis.readthedocs.io/en/latest/tutorial.html

The tooltip in this function is set-up so that it will show lists of adjacent neighbors when hovering on a node. I would like to display this same information, but would also like to display the associated edge weight for each neighbor.

I know that weight is being accounted for in my visualization since the edge width is changing depending on the weight, but the few attempts I've made haven't shown any change in the tooltip.

Here is what I've attempted in addition to the code responsible for the tooltip (Tooltip section is toward the bottom, just below the neighbor_map object):

HCP_net = Network(height='750px', width='100%', bgcolor='#222222', font_color='white')

HCP_net.barnes_hut()

sources = df2['HCP_Name']
targets = df2['HCPOffset_Name']
weights = df2['PATIENT_ID (DCOUNT)']

edge_data = zip(sources, targets, weights)

for e in edge_data:
    src = e[0]
    dst = e[1]
    w = e[2]
    
    HCP_net.add_node(src, src, title=src)
    HCP_net.add_node(dst, dst, title=dst)
    HCP_net.add_edge(src, dst, value=w)
    
neighbor_map = HCP_net.get_adj_list()
node_weight = HCP_net.get_edges() #my attempt at creating a weight object to call, if I call print(len(node_weight)) I get an integer so I know this is working

for node in HCP_net.nodes:
    node['title'] += ' Neighbors: <br>' + '<br>'.join(neighbor_map[node['id']])
    node['value'] = len(neighbor_map[node['id']])
    node['value'] = len(neighbor_map.keys()) #This called by itself 
 (print(len(neighbor_map.keys())) also displays the same integer as my node_weight object
    

I think I'm just not quite understanding how to correctly call the node['value'] to result in a new display in the tool tip. Any assistance is greatly appreciated!

Jmackerl
  • 33
  • 7

1 Answers1

1

The node['title'] variable stores the information being displayed while hovering the nodes. To add the weights to the information displayed, you first need to associate them to their corresponding neighbors and then change the node['title'] variable such that it contains the concatenated information neighbor and weight . You can find more details on how to do that in the code below:

from pyvis.network import Network
import pandas as pd

got_net = Network(height='750px', width='100%', bgcolor='#222222', font_color='white')

# set the physics layout of the network
got_net.barnes_hut()
got_data = pd.read_csv('https://www.macalester.edu/~abeverid/data/stormofswords.csv')

sources = got_data['Source']
targets = got_data['Target']
weights = got_data['Weight']

edge_data = zip(sources, targets, weights)

for e in edge_data:
    src = e[0]
    dst = e[1]
    w = e[2]

    got_net.add_node(src, src, title=src)
    got_net.add_node(dst, dst, title=dst)
    got_net.add_edge(src, dst, value=w)

neighbor_map = got_net.get_adj_list()
edges = got_net.get_edges()
nodes=got_net.get_nodes()

N_nodes=len(nodes)
N_edges=len(edges)


weights=[[] for i in range(N_nodes)]

#Associating weights to neighbors
for i in range(N_nodes): #Loop through nodes
    for neighbor in neighbor_map[nodes[i]]: #and neighbors
        for j in range(N_edges): #associate weights to the edge between node and neighbor
            if (edges[j]['from']==nodes[i] and edges[j]['to']==neighbor) or \
               (edges[j]['from']==neighbor and edges[j]['to']==nodes[i]):
                weights[i].append(edges[j]['value'])
    

for node,i in zip(got_net.nodes,range(N_nodes)):
   
    node['value']=len(neighbor_map[node['id']])
    node['weight']=[str(weights[i][k]) for k in range(len(weights[i]))]
    list_neighbor=list(neighbor_map[node['id']]) 
    #Concatenating neighbors and weights
    hover_str=[list_neighbor[k]+' '+ node['weight'][k] for k in range(node['value'])]
    #Setting up node title for hovering 
    node['title']+=' Neighbors:<br>'+'<br>'.join(hover_str)
    
got_net.show('gameofthrones.html')

And the output gives:

enter image description here

jylls
  • 4,395
  • 2
  • 10
  • 21
  • 1
    Thank you! This is great, after posting this questions I realized how I was going about the problem wrong, but still couldn't implement the proper solution myself. – Jmackerl Jan 31 '22 at 05:50