I am attempting to build a network graph using NetworkX and Bokeh. I am using the NetworkX from_pandas_edgelist
function to add data for the graph. I would like
Good question, and accepted answer (from which I was able to extend my code to give colored nodes based on the Pandas dataframe column).
import warnings
warnings.filterwarnings("ignore", category=UserWarning)
import networkx as nx
import matplotlib.pyplot as plt
import pandas as pd
df = pd.read_csv('pers_org.tsv', sep='\t')
# (TSV copied from a PostgreSQL database, hence the "id" column.)
df.sort_values(by=['id'])
'''
id person organization
0 1 Robert_Bigelow BAASS
1 2 Robert_Bigelow AATIP
2 3 Robert_Bigelow NIDS
3 4 Robert_Bigelow Skinwalker_Ranch
14 5 Luis_Elizondo AATIP
4 6 Colm_Kelleher AATIP
5 7 Colm_Kelleher NIDS
6 8 Colm_Kelleher Skinwalker_Ranch
7 9 Tom_DeLonge TTSA
8 10 Luis_Elizondo TTSA
9 11 Hal_Puthoff TTSA
10 12 Chris_Mellon TTSA
11 13 Douglas_Kurth US_Navy
12 14 Douglas_Kurth Lockheed
13 15 Douglas_Kurth BAASS
'''
G = nx.from_pandas_edgelist(df, source='person', target='organization', \
create_using=nx.DiGraph)
colors = []
for node in G:
if node in df["person"].values:
colors.append("lightblue")
else: colors.append("lightgreen")
print(colors)
# ['lightblue', 'lightgreen', 'lightgreen', 'lightgreen', 'lightgreen',
# 'lightblue', 'lightblue', 'lightgreen', 'lightblue', 'lightblue',
# 'lightblue', 'lightblue', 'lightgreen', 'lightgreen']
plt.figure(figsize=(15,10))
# <Figure size 1500x1000 with 0 Axes>
nx.draw(G, pos = nx.nx_pydot.graphviz_layout(G), \
node_size=1200, node_color=colors, linewidths=0.25, \
font_size=10, font_weight='bold', with_labels=True)
plt.show()
See also How to set colors for nodes in networkx python?
pers_org.tsv
id person organization
1 Robert_Bigelow BAASS
2 Robert_Bigelow AATIP
3 Robert_Bigelow NIDS
4 Robert_Bigelow Skinwalker_Ranch
5 Luis_Elizondo AATIP
6 Colm_Kelleher AATIP
7 Colm_Kelleher NIDS
8 Colm_Kelleher Skinwalker_Ranch
9 Tom_DeLonge TTSA
10 Luis_Elizondo TTSA
11 Hal_Puthoff TTSA
12 Chris_Mellon TTSA
13 Douglas_Kurth US_Navy
14 Douglas_Kurth Lockheed
15 Douglas_Kurth BAASS
Although I did not do this here, if you want to add node borders and thicken the node border lines (node edge thickness: linewidths
), do the following.
nx.draw(G, pos = nx.nx_pydot.graphviz_layout(G), \
node_size=1200, node_color=colors, linewidths=2.0, \
font_size=10, font_weight='bold', with_labels=True)
# Get current axis:
ax = plt.gca()
ax.collections[0].set_edgecolor('r')
# r : red (can also use #FF0000) | b : black (can also use #000000) | ...
plt.show()
After the old Edit:
Can't give too much context as I am not super familiar with bokeh, but looks like you can use a similar approach to what I did initially just instead of passing the "color_map" do your draw function you have to stick your data in here graph_renderer.node_renderer.data_source.data['colors']
Anyway this seems to do the job, Good luck dude.
relation = pd.DataFrame({
"company":["Google", "Google", "Amazon", "Amazon", "Amazon",
"Apple", "Apple", "Apple"],
"client":["AT&T", "Cisco", "Facebook", "Snap", "Microsoft",
"Intel", "IBM", "Visa"]})
G=nx.from_pandas_edgelist(relation, 'company', 'client')
colors = []
for node in G:
if node in relation["client"].values:
colors.append("blue")
else: colors.append("green")
plot = Plot(plot_width=1000, plot_height=800,
x_range=Range1d(-1.1, 1.1), y_range=Range1d(-1.1, 1.1))
plot.title.text = "Company - Client Network"
node_hover_tool = HoverTool(tooltips=[("Company Name", "@index")])
plot.add_tools(node_hover_tool, BoxZoomTool(), ResetTool())
graph_renderer = from_networkx(G, nx.spring_layout, scale=1, center=(0, 0))
graph_renderer.node_renderer.data_source.data['colors'] = colors
graph_renderer.node_renderer.glyph = Circle(size=20, fill_color='colors')
graph_renderer.edge_renderer.glyph = MultiLine(line_color="red", line_alpha=0.8, line_width=1)
plot.renderers.append(graph_renderer)
output_file("boo.html")
show(plot)