Tutorial 4: Visualizing Evolving Communities
This tutorial demonstrates how to create effective visualizations for understanding and analyzing evolving communities in temporal networks.
Prerequisites
# Install the package if you haven't already
# pip install 'dyn-benchmark[all]'
# Import required modules
from dyn.benchmark.generator.groundtruth_generator import GroundtruthGenerator
from dyn.core.communities import Membership
from dyn.drawing.sankey_drawing import plot_sankey
1. Visualizing Community Flow with Sankey Diagrams
First, let’s create a benchmark to visualize:
# Create a generator with parameters to create interesting community evolution
generator = GroundtruthGenerator(seed=42)
groundtruth = generator.generate()
# Extract membership information
membership = Membership.from_tcommlist(groundtruth.tcommlist)
Sankey diagrams are ideal for visualizing how communities evolve over time:
# Create a Sankey diagram of community evolution
plot_sankey(membership.community_graph)
Let’s understand the key components of this visualization:
# Extract and print information about the community flow
for t in sorted(community_flow_graph.snapshots):
communities_at_t = list(community_flow_graph.snapshot_nodes(t))
print(f"Snapshot {t}: {len(communities_at_t)} communities")
for community in communities_at_t:
# Get predecessors (sources of incoming members)
predecessors = list(community_flow_graph.predecessors(community))
# Get successors (destinations of outgoing members)
successors = list(community_flow_graph.successors(community))
# Get size of the community
size = community_flow_graph.node_size(community)
print(f" Community {community}: Size={size}, Predecessors={len(predecessors)}, Successors={len(successors)}")
Complete Example
# Install the package if you haven't already
# pip install 'dyn-benchmark[all]'
# Import required modules
from dyn.benchmark.generator.groundtruth_generator import GroundtruthGenerator
from dyn.core.communities import Membership
from dyn.drawing.sankey_drawing import plot_sankey
# Create a generator with parameters to create interesting community evolution
generator = GroundtruthGenerator(seed=42)
groundtruth = generator.generate()
# Extract membership information
membership = Membership.from_tcommlist(groundtruth.tcommlist)
# Create a Sankey diagram of community evolution
plot_sankey(membership.community_graph)
# Extract and print information about the community flow
for t in sorted(community_flow_graph.snapshots):
communities_at_t = list(community_flow_graph.snapshot_nodes(t))
print(f"Snapshot {t}: {len(communities_at_t)} communities")
for community in communities_at_t:
# Get predecessors (sources of incoming members)
predecessors = list(community_flow_graph.predecessors(community))
# Get successors (destinations of outgoing members)
successors = list(community_flow_graph.successors(community))
# Get size of the community
size = community_flow_graph.node_size(community)
print(f" Community {community}: Size={size}, Predecessors={len(predecessors)}, Successors={len(successors)}")
2. Visualizing Network Snapshots with Communities
Let’s visualize the network structure at each snapshot, with nodes colored by community:
# Import required modules
from dyn.benchmark.generator.groundtruth_generator import GroundtruthGenerator
from dyn.core.communities import Membership
from dyn.drawing.sankey_drawing import plot_sankey
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
import os
def plot_network_with_communities(graph, snapshot, membership, figsize=(10, 8)):
"""Plot a network with nodes colored by community"""
plt.figure(figsize=figsize)
# Get community assignments for this snapshot
communities = {}
for row in membership.tcommlist:
if row.snapshot == snapshot:
communities[row.node_id] = row.evolving_community_id
# Create a color map for communities
unique_communities = set(communities.values())
colors = plt.cm.tab20(np.linspace(0, 1, len(unique_communities)))
color_map = {com: colors[i % len(colors)] for i, com in enumerate(unique_communities)}
# Assign colors to nodes
node_colors = [color_map.get(communities.get(node, -1), 'gray') for node in graph.nodes]
# Compute layout (with seed for reproducibility)
pos = nx.spring_layout(graph, seed=42)
# Draw the network
nx.draw_networkx(
graph,
pos=pos,
node_color=node_colors,
node_size=80,
with_labels=False,
width=0.5,
alpha=0.8
)
# Add a legend for communities
handles = [plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=color,
markersize=10, label=f'Community {com}')
for com, color in color_map.items()]
plt.legend(handles=handles, loc='upper right', bbox_to_anchor=(1.15, 1))
plt.title(f"Network Communities at Snapshot {snapshot}", fontsize=14)
plt.axis('off')
plt.tight_layout()
return plt.gcf()
# Plot each snapshot
snapshots = sorted(groundtruth.graphs.keys())
for snapshot in snapshots:
graph = groundtruth.graphs[snapshot]
fig = plot_network_with_communities(graph, snapshot, membership)
plt.savefig(f"network_snapshot_{snapshot}.png", dpi=300, bbox_inches='tight')
plt.show()