0

I have a dataset where the NetworkX graph is sized and colored by the degree attribute. I am looking to add a slider to the graph so that depending on the degree that is selected, the graph will dynamically update the nodes and edges. I have the slider showing up in Jupyter, however, it's not updating when selecting a new value. Any advice on how this can be done? Here is my code that I am working with currently:

df = pd.read_csv('data/book1.csv')
G = nx.from_pandas_edgelist(df, 'Node', 'Target', 'SimScore')

#Reference: https://stackoverflow.com/questions/18218931/find-highest-weight-edges-for-a-given-node
#Calculate degree for each node and remove instances when less than user defined threshold
for node in G.nodes():
    edges = G.edges(node, data = True)
    if len(edges) > 0:
        for edge in list(edges):
            if edge[2]['SimScore'] < 5:
                G.remove_edge(edge[0], edge[1])

#Reference: https://stackoverflow.com/questions/18261587/python-networkx-remove-nodes-and-edges-with-some-condition
remove = [node for node, degree in G.degree() if degree == 0]
G.remove_nodes_from(remove)

G_dict = dict(G.degree())

#Add degree as node attribute
nx.set_node_attributes(G, name = 'degree', values = G_dict)

#Define color pallete
color_palette = Reds8

#Show hover tooltip with "nodes" being the user input songs and the degree
#Reference: https://docs.bokeh.org/en/latest/docs/user_guide/tools.html#hovertool
TOOLTIPS = [("Song", "@index"), ("Degree", "@degree")]

#Create plot with tooltips, ranges, and title
plot = figure(tooltips = TOOLTIPS, tools = "pan, wheel_zoom, save, reset", active_scroll = "wheel_zoom", x_range = Range1d(-10.1, 10.1), y_range = Range1d(-10.1, 10.1), title = "New Music Network Graph")

#Network graph object
networkG = from_networkx(G, networkx.spring_layout, scale = 10, center = (0,0))

#Set node size and color
min_degree = min(networkG.node_renderer.data_source.data['degree'])
max_degree = max(networkG.node_renderer.data_source.data['degree'])

networkG.node_renderer.glyph = Circle(size = 'degree', fill_color = linear_cmap('degree', color_palette, min_degree, max_degree))
networkG.edge_renderer.glyph = MultiLine(line_alpha = 0.5, line_width = 1)

plot.renderers.append(networkG)

########### Slider ###########

G_dict_slider = {'Nodes': list(G_dict.keys()), 'Degrees': list(G_dict.values())}
source = ColumnDataSource(data = G_dict_slider)

degree_slider = Slider(start = min_degree, end = max_degree, value = 20, step = 1, title = "Degrees")

callback = CustomJS(args = dict(source = source, deg = degree_slider), code = '''
    const new_data = source.data;
    const new_nodes = new_data['Node'];
    const new_degrees = new_data['Degrees'];
    var new_min_degree = min(networkG.node_renderer.data_source.new_degrees);
    var new_max_degree = max(networkG.node_renderer.data_source.new_degrees);
    networkG.node_renderer.glyph = Circle(size = new_degrees, fill_color = linear_cmap(new_degrees, color_palette, new_min_degree, new_max_degree));
    networkG.edge_renderer.glyph = MultiLine(line_alpha = 0.5, line_width = 1);
    source.change.emit();
    ''')

degree_slider.js_on_change('value', callback)

layout = row(plot, column(degree_slider),)

show(layout)

Here is the current output: Networkx Graph

Thanks in advance!

0 Answers0