This chapter will cover how to plot network node/link graphs in Bokeh using NetworkX. For information on creating graph renderers from a low level, see Visualizing Network Graphs
from bokeh.io import show, output_notebook
from bokeh.plotting import figure
#nbi:hide_out
# Make all outputs INLINE for default (why a hell this is needed !!!)
output_notebook()
The easiest way to plot network graphs with Bokeh is to use the from_networkx
function. This function accepts any NetworkX graph and returns a Bokeh GraphRenderer
that can be added to a plot. The GraphRenderer
has node_renderer
and edge_renderer
properties that contain the Bokeh renderers that draw the nodes and edges, respectively.
The example below shows a Bokeh plot of nx.desargues_graph()
, setting some of the node and edge properties.
import networkx as nx
from bokeh.models import Range1d, Plot
from bokeh.plotting import from_networkx
G = nx.desargues_graph()
# We could use figure here but don't want all the axes and titles
plot = Plot(x_range=Range1d(-2, 2), y_range=Range1d(-2, 2))
# Create a Bokeh graph from the NetworkX input using nx.spring_layout
graph = from_networkx(G, nx.spring_layout, scale=1.8, center=(0,0))
plot.renderers.append(graph)
# Set some of the default node glyph (Circle) properties
graph.node_renderer.glyph.update(size=20, fill_color="orange")
# Set some edge properties too
graph.edge_renderer.glyph.line_dash = [2,2]
show(plot)
The node_renderer
and edge_renderer
properties of the graph renderer each have a data_source
that is a standard ColumnDataSource
that you can add new data to, e.g. to drive a hover tool, or to specify colors for the renderer. The example below demonstates both.
from bokeh.models import HoverTool
from bokeh.palettes import Category20_20
G = nx.desargues_graph() # always 20 nodes
# We could use figure here but don't want all the axes and titles
plot = Plot(x_range=Range1d(-2, 2), y_range=Range1d(-2, 2))
# Create a Bokeh graph from the NetworkX input using nx.spring_layout
graph = from_networkx(G, nx.spring_layout, scale=1.8, center=(0,0))
plot.renderers.append(graph)
# Add some new columns to the node renderer data source
graph.node_renderer.data_source.data['index'] = list(range(len(G)))
graph.node_renderer.data_source.data['colors'] = Category20_20
graph.node_renderer.glyph.update(size=20, fill_color="colors")
plot.add_tools(HoverTool(tooltips="index: @index"))
show(plot)
Bokeh graph renderers have inspection_policy
and selection_policy
properties. These can be used to control how hover inspections highlight the graph, or how selection tools make selections. These properties may be set to any of the inpection policies in bokeh.graphs
. For instance, if a user hovers over a node, you may wish to highlight all the associated edges as well. This can be accomplished by setting the inspection policy:
graph.inspection_policy = NodesAndLinkedEdges()
as the example below demonstrates.
from bokeh.models.graphs import NodesAndLinkedEdges
from bokeh.models import Circle, HoverTool, MultiLine
G = nx.gnm_random_graph(15, 30)
# We could use figure here but don't want all the axes and titles
plot = Plot(x_range=Range1d(-2, 2), y_range=Range1d(-2 ,2))
# Create a Bokeh graph from the NetworkX input using nx.spring_layout
graph = from_networkx(G, nx.spring_layout, scale=1.8, center=(0,0))
plot.renderers.append(graph)
# Blue circles for nodes, and light grey lines for edges
graph.node_renderer.glyph = Circle(size=25, fill_color='#2b83ba')
graph.edge_renderer.glyph = MultiLine(line_color="#cccccc", line_alpha=0.8, line_width=2)
# green hover for both nodes and edges
graph.node_renderer.hover_glyph = Circle(size=25, fill_color='#abdda4')
graph.edge_renderer.hover_glyph = MultiLine(line_color='#abdda4', line_width=4)
# When we hover over nodes, highlight adjecent edges too
graph.inspection_policy = NodesAndLinkedEdges()
plot.add_tools(HoverTool(tooltips=None))
show(plot)