Graph Visualization
Tutorial
Graph Visualization
Create interactive graph visualizations with pyvis and plotly
What You'll Learn
- NetworkX Conversion - Build a NetworkX graph from query results
- Interactive Visualization - Render graph networks with pyvis
- Community Coloring - Color nodes by Louvain community membership
- Centrality Sizing - Size nodes by PageRank score
- Charts - Create analytical charts with plotly
1
Setup
Connect to the platform and provision tutorial resources
# Cell 1 — ParametersUSERNAME = "_FILL_ME_IN_" # Set your email before running# Cell 2 — Connect and provisionfrom graph_olap import GraphOLAPClientclient = GraphOLAPClient(username=USERNAME)
from notebook_setup import provisionpersonas, conn = provision(USERNAME)analyst = personas["analyst"]
print(f"Connected | {conn.query_scalar('MATCH (n) RETURN count(n)')} nodes")
2
Converting to NetworkX
Build a NetworkX DiGraph from query results
# Query nodes and edges, then convert to a NetworkX DiGraphresult = conn.query( "MATCH (a:Customer)-[r:SHARES_ACCOUNT]->(b:Customer) " "RETURN a.id AS src, a.id AS src_name, " "b.id AS dst, b.id AS dst_name LIMIT 50")
G = result.to_networkx()
print(f"NetworkX graph: {G.number_of_nodes()} nodes, {G.number_of_edges()} edges")print(f"Type: {type(G).__module__}.{type(G).__name__}")print(f"Sample nodes: {list(G.nodes)[:5]}")
3
Interactive Visualization with pyvis
Render an interactive graph network in the browser
# Guard: check if pyvis is availabletry: from pyvis.network import Network HAS_PYVIS = True print("pyvis is available")except ImportError: HAS_PYVIS = False print("Install pyvis for interactive graphs: pip install pyvis")if HAS_PYVIS: net = Network(height="500px", width="100%", notebook=True, directed=True)
# Add nodes with labels for node_id in G.nodes: label = G.nodes[node_id].get("src_name", node_id) net.add_node(node_id, label=str(label), title=f"Customer {node_id}")
# Add edges for src, dst in G.edges: net.add_edge(src, dst)
# Configure physics for layout net.toggle_physics(True) net.show("/tmp/graph_basic.html") print(f"Interactive graph saved to /tmp/graph_basic.html ({G.number_of_nodes()} nodes)")else: print("Skipped: pyvis not installed")
4
Coloring by Algorithm Results
Run Louvain community detection and color nodes by community
# Run Louvain community detection via the SDK APIconn.algo.louvain( node_label="Customer", edge_type="SHARES_ACCOUNT", property_name="viz_community", resolution=1.0,)
# Query community assignments via regular Cyphercommunities = conn.query( "MATCH (c:Customer) WHERE c.viz_community IS NOT NULL " "RETURN c.id AS id, c.viz_community AS communityId LIMIT 50")
# Build a community lookupcommunity_map = {row["id"]: row["communityId"] for row in communities}unique_communities = sorted(set(community_map.values()))print(f"Detected {len(unique_communities)} communities across {len(community_map)} nodes")
# Assign colors per communityCOLORS = ["#4e79a7", "#f28e2b", "#e15759", "#76b7b2", "#59a14f", "#edc948", "#b07aa1", "#ff9da7", "#9c755f", "#bab0ac"]color_map = {cid: COLORS[i % len(COLORS)] for i, cid in enumerate(unique_communities)}
if HAS_PYVIS: net = Network(height="500px", width="100%", notebook=True, directed=True) for node_id in G.nodes: cid = community_map.get(node_id, 0) color = color_map.get(cid, "#999999") net.add_node(node_id, label=str(node_id), color=color, title=f"Customer {node_id} | Community {cid}") for src, dst in G.edges: net.add_edge(src, dst) net.toggle_physics(True) net.show("/tmp/graph_communities.html") print(f"Community-colored graph saved to /tmp/graph_communities.html")else: print("Skipped: pyvis not installed")
5
Sizing by Centrality
Run PageRank and size nodes proportionally
# Run PageRank via the SDK APIconn.algo.pagerank( node_label="Customer", edge_type="SHARES_ACCOUNT", property_name="viz_pr",)
# Query scores via regular Cypherpagerank = conn.query( "MATCH (c:Customer) WHERE c.viz_pr IS NOT NULL " "RETURN c.id AS id, c.viz_pr AS score " "ORDER BY c.viz_pr DESC LIMIT 50")
# Build a score lookupscore_map = {row["id"]: row["score"] for row in pagerank}max_score = max(score_map.values()) if score_map else 1.0print(f"PageRank scores for {len(score_map)} nodes (max={max_score:.4f})")
if HAS_PYVIS: net = Network(height="500px", width="100%", notebook=True, directed=True) for node_id in G.nodes: score = score_map.get(node_id, 0.0) cid = community_map.get(node_id, 0) color = color_map.get(cid, "#999999") # Scale node size: 10 (min) to 40 (max) size = 10 + 30 * (score / max_score) net.add_node(node_id, label=str(node_id), color=color, size=size, title=f"Customer {node_id} | PR={score:.4f}") for src, dst in G.edges: net.add_edge(src, dst) net.toggle_physics(True) net.show("/tmp/graph_pagerank.html") print(f"PageRank-sized graph saved to /tmp/graph_pagerank.html")else: print("Skipped: pyvis not installed")
6
Charts with plotly
Create analytical bar and scatter charts
# Guard: check if plotly is availabletry: import plotly.express as px HAS_PLOTLY = True print("plotly is available")except ImportError: HAS_PLOTLY = False print("Install plotly for charts: pip install plotly")if HAS_PLOTLY: # Bar chart: top 10 nodes by PageRank (already computed as viz_pr property) pr_df = conn.query_df( "MATCH (c:Customer) WHERE c.viz_pr IS NOT NULL " "RETURN c.id AS id, c.id AS name, c.viz_pr AS score " "ORDER BY c.viz_pr DESC LIMIT 10", backend="pandas", ) fig = px.bar(pr_df, x="name", y="score", title="Top 10 Customers by PageRank") fig.write_html("/tmp/chart_pagerank.html") print("Bar chart saved to /tmp/chart_pagerank.html")
# Scatter chart: centrality vs degree degree_df = conn.query_df( "MATCH (c:Customer) WHERE c.viz_pr IS NOT NULL " "WITH c, c.viz_pr AS pagerank " "MATCH (c)-[r:SHARES_ACCOUNT]-() " "RETURN c.id AS id, pagerank, count(r) AS degree", backend="pandas", ) fig2 = px.scatter( degree_df, x="degree", y="pagerank", hover_data=["id"], title="PageRank vs Degree (SHARES_ACCOUNT)", ) fig2.write_html("/tmp/chart_scatter.html") print("Scatter chart saved to /tmp/chart_scatter.html")else: print("Skipped: plotly not installed")
7
Using show()
Built-in auto-visualization for query results
# show() automatically detects graph structure and renders appropriatelyresult = conn.query( "MATCH (a:Customer)-[:SHARES_ACCOUNT]->(b:Customer) " "RETURN a.id AS src, b.id AS dst LIMIT 10")result.show()print(f"\nshow() rendered {result.row_count} rows with auto-detection")Key Takeaways
to_networkx()converts query results into a NetworkX DiGraph for graph analysis- pyvis renders interactive, physics-enabled graph visualizations as HTML files
- Louvain community IDs can drive node coloring to reveal cluster structure
- PageRank scores can scale node sizes to highlight important nodes
- plotly creates publication-quality bar charts and scatter plots from query data
show()provides quick built-in visualization without extra dependencies