1

Following this example, I am trying to build a network graph using Bokeh where I can use a select widget to filter my data. My data will look something like this:

source  target  var1    var2
        a   c   1.0     0.0
        b   g   2.0     0.0
        c   e   3.0     0.0
        e   a   0.0     1.0
        f   h   0.0     2.0

And can be recreated using this code:

d = {'weight': [1, 2,3,1,2], 'var': ["var1","var1","var1","var2", "var2"], 'source': ["a", "b","c","e","f"], 'target': ["c","g","e","a","h"]}
df1 = pd.DataFrame(data=d)
df2 = df1.pivot( index= ["source","target"], values = "weight", columns = "var").reset_index()
df2 = df2.fillna(0)

Basically, I want to create the network graph where I can filter the columns (var1, var2) and they will become the weight attribute in my graph. (Filtering for when this weight value is greater than 0.)

To accomplish this I tried the following. But even though the graph renders, when I change the selected value nothing happens. I don't see any errors in the console either. I am not sure what I am doing wrong, probably something in the JS call because I am new to this, but I am trying to reproduce the example as closely as possible and still not sure where im going wrong. Please help!

from bokeh.plotting import from_networkx
from bokeh.plotting import figure, output_file, show
from bokeh.models import Plot, Range1d, MultiLine, Circle, HoverTool,NodesAndLinkedEdges,EdgesAndLinkedNodes, TapTool, BoxSelectTool,ColumnDataSource
from bokeh.models import CustomJS, ColumnDataSource, Select, Column

HOVER_TOOLTIPS = [("Search Term", "@index")]

title = "my title"
plot = figure(tooltips = HOVER_TOOLTIPS,
              tools="pan,wheel_zoom", 
              active_scroll='wheel_zoom',
              x_range=Range1d(-10.1, 10.1), 
              y_range=Range1d(-10.1, 10.1), 
              title=title, plot_width=1000
             )

category_default = "var1"
unique_categories = ["var1","var2"]

subset = df2
subset_data = subset[["var1","var2"]].to_dict("list") 

source = ColumnDataSource({
        "weight": subset[category_default],   
        "source": subset.source,
        "target": subset.target

    })

a = pd.DataFrame(source.data)

G = nx.from_pandas_edgelist(a[a["weight"] >0], edge_attr = "weight")

network_graph = from_networkx(G, networkx.spring_layout, scale=10, center=(0, 0), )
network_graph.edge_renderer.glyph = MultiLine(line_alpha=0.5, line_width="weight" )

select = Select(title='Category Selection', value=category_default, options=unique_categories)

callback = CustomJS(
        args={"subset_data": subset_data, "source": source},
    
        code="""
            
            source.data['weight'] = subset_data[cb_obj.value];
            source.change.emit();
            
        """)



plot.renderers.append(network_graph)
select.js_on_change("value", callback)

show(Column(plot, select))
Alexis Philip
  • 517
  • 2
  • 5
  • 23
  • 1
    Instant +1 because you provided a way to reconstruct a similar `df`! However what is `subset`? – Be Chiller Too Oct 29 '21 at 14:55
  • Thank you. Been trying this one for days. I just renamed my df (df2) as subset to follow as easily as possible this example https://stackoverflow.com/questions/68100023/python-bokeh-how-the-change-data-source-by-filtering-rows-by-column-value-from – linacarrillo Oct 29 '21 at 14:58
  • so you want to use var1 as a weight on the edges when it's >0 right ? – Reine Baudache Nov 05 '21 at 15:38
  • yes, this is the way to filter for me for relevant data. I don't know if these are the modifications causing the issue – linacarrillo Nov 05 '21 at 15:47

0 Answers0