Reputation: 2188
I am trying to display a graph using networkx with bokeh 12.7
that
import pandas as pd
import numpy as np
import networkx as nx
import seaborn as sns
from bokeh.io import show, output_notebook #output_file,
from bokeh.plotting import figure
from bokeh.models.graphs import from_networkx
from bokeh.models import GraphRenderer, StaticLayoutProvider, LinearColorMapper, ColumnDataSource
from bokeh.palettes import Spectral8, Spectral4
G = nx.karate_club_graph()
# Some Random index
node_color = {k:v for k, v in enumerate(np.random.uniform(low=0, high=21, size=(G.number_of_nodes(),)).round(1))}
# Set node attributes
nx.set_node_attributes(G, 'node_color', node_color)
nx.set_node_attributes(G, 'node_size', G.degree())
bokeh
with cubehelix_palette
# Map cubehelix_palette
palette = sns.cubehelix_palette(21)
pal_hex_lst = palette.as_hex()
mapper = LinearColorMapper(palette=pal_hex_lst, low=0, high=21)
# Initiate bokeh plot
plot = figure(title="Resized Node Demo", x_range=(-1.1,1.1), y_range=(-1.1,1.1),
tools="", toolbar_location=None)
# Graph renderer using nx
graph = from_networkx(G, nx.spring_layout, scale=2, center=(0,0))
# Style node
graph.node_renderer.glyph = Circle(size='node_size', fill_color={'field': 'node_color', 'transform': mapper})
plot.renderers.append(graph)
output_notebook()
#output_file("networkx_graph.html")
show(plot)
Glyph refers to nonexistent column name
# 1. Create Plot container
plot = figure(title=endNode, x_range=(-1.1,1.1), y_range=(-1.1,1.1),
tools="", toolbar_location=None)
# 2. Create graph plot comtainer
graph = GraphRenderer()
node_link_dict = nx.readwrite.json_graph.node_link_data(G)
node_df = pd.DataFrame(node_link_dict['nodes'])
node_cds = ColumnDataSource.from_df(graph_data.node_df)
graph.node_renderer.data_source.data = node_cds
# 3. Set Node Style
graph.node_renderer.glyph = Circle(size='node_size', fill_color='node_color')
Any thoughts?
Upvotes: 4
Views: 4814
Reputation: 129
Was looking for something similar. Maybe it helps someone else.
You can change it in the same way as changing the node size. So there is no need to use pandas which could also mix up sth. if used in the wrong way.
You can create a list where the colors for each node is stored. Then add the color information:
colors = [...]
graph.node_renderer.data_source.data['colors'] = colors
graph.node_renderer.glyph = Circle(size='degrees', fill_color='colors')
Or if you really want to use node attributes then you can do this using a dict: create a list with all colors first:
colors = [...]
colors = dict(zip(G.nodes, colors))
nx.set_node_attributes(G, {k:v for k,v in colors.items()},'colors' )
graph.node_renderer.glyph = Circle(size='degrees', fill_color='colors')
Upvotes: 1
Reputation: 46
I was trying to set the node size based on the degree centrality as well and was able to do so using
graph.node_renderer.data_source = source
I can see the differing sizes and colors (see attached image), although I could not find the reason for the below error yet
E-1010 (CDSVIEW_SOURCE_DOESNT_MATCH): CDSView used by Glyph renderer must have a source that matches the Glyph renderer's data source: GlyphRenderer(id='035dd78a-7bff-40d1-8357-d7193222ca02', ...)
#just to make the sizes visible
node_size = {k:5*v for k,v in G.degree().items()}
### set node attributes
nx.set_node_attributes(G, 'node_color', node_color)
nx.set_node_attributes(G, 'node_size', node_size)
source=ColumnDataSource(pd.DataFrame.from_dict({k:v for k,v in G.nodes(data=True)},orient='index'))
mapper = LinearColorMapper(palette=pal_hex_lst, low=0, high=21)
### Initiate bokeh plot
plot = figure(title="Resized Node Demo", x_range=(-1.1,1.1), y_range=(-1.1,1.1),
tools="", toolbar_location=None)
# Graph renderer using nx
graph = from_networkx(G, nx.spring_layout, scale=2, center=(0,0))
# Style node
graph.node_renderer.data_source = source
graph.node_renderer.glyph = Circle(size='node_size', fill_color={'field': 'node_color', 'transform': mapper})
plot.renderers.append(graph)
Upvotes: 3