A community in a graph is a cluster of nodes that are densely connected to each other but loosely connected to the rest of the network. Detecting communities reveals hidden structure: friend groups in social networks, topic clusters in citation graphs, functional modules in protein interaction networks, or customer segments in purchase graphs. NetworkX provides several community detection algorithms — they differ in speed, determinism, and the type of communities they find. ### Greedy Modularity Communities The greedy modularity algorithm builds communities by repeatedly merging nodes and groups to maximize modularity — a measure of how much denser the community's internal edges are compared to a random graph with the same degree sequence. It's deterministic and works well on medium-sized graphs.
import networkx as nx
from networkx.algorithms import community
import matplotlib.pyplot as plt
G = nx.karate_club_graph() # classic 34-node social network
comms = list(community.greedy_modularity_communities(G))
print(f"Found {len(comms)} communities")
for i, c in enumerate(comms):
print(f" Community {i+1}: {sorted(c)}")- `nx.karate_club_graph()` is a well-known benchmark: 34 members of a karate club, with edges representing social ties outside the club. - `greedy_modularity_communities` returns a list of frozensets, each containing the node IDs in that community. - The algorithm typically finds 4 communities in the karate club graph, which corresponds closely to the known ground-truth split. ### Visualizing Communities Assigning a distinct color to each community makes the structure immediately visible when the graph is drawn with a force-directed layout.
import networkx as nx
from networkx.algorithms import community
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
G = nx.karate_club_graph()
comms = list(community.greedy_modularity_communities(G))
cmap = plt.cm.tab10
node_color = {}
for i, comm in enumerate(comms):
for node in comm:
node_color[node] = cmap(i / 10)
colors = [node_color[n] for n in G.nodes()]
pos = nx.spring_layout(G, seed=42)
plt.figure(figsize=(8, 7))
nx.draw(G, pos, node_color=colors, with_labels=True,
node_size=400, font_size=8, edge_color="gray", width=0.5)
plt.title(f"Greedy Modularity Communities ({len(comms)} groups)")
plt.tight_layout()
plt.show()- `cmap(i / 10)` maps each community index to a distinct color from the `tab10` palette. - `nx.spring_layout(G, seed=42)` places nodes using a force-directed algorithm; `seed` makes the layout reproducible. - Nodes in the same community cluster together in the layout, showing that the algorithm recovers visually coherent groups. ### Label Propagation Label propagation is a fast, randomized alternative. Each node starts with a unique label, then repeatedly adopts the most common label among its neighbors. It converges quickly but produces different results on each run.
import networkx as nx
from networkx.algorithms import community
import matplotlib.pyplot as plt
rng = 0 # seed for reproducibility
G = nx.karate_club_graph()
comms_lp = list(community.label_propagation_communities(G))
print(f"Label propagation: {len(comms_lp)} communities")
# Assign colors and draw
cmap = plt.cm.tab10
node_color = {}
for i, comm in enumerate(comms_lp):
for node in comm:
node_color[node] = cmap(i / 10)
colors = [node_color[n] for n in G.nodes()]
pos = nx.spring_layout(G, seed=42)
plt.figure(figsize=(8, 7))
nx.draw(G, pos, node_color=colors, with_labels=True,
node_size=400, font_size=8, edge_color="gray", width=0.5)
plt.title(f"Label Propagation Communities ({len(comms_lp)} groups)")
plt.tight_layout()
plt.show()- `label_propagation_communities` is O(m) — linear in the number of edges — making it practical for large graphs where greedy modularity is too slow. - The number of communities is not fixed: the algorithm finds as many as the label propagation naturally settles into. - Results may differ between runs; wrap the call in a loop and aggregate across multiple runs if stability matters. ### Modularity Score Modularity is the standard quality measure for a community partition. It ranges from −0.5 to 1; values above 0.3 generally indicate meaningful structure.
import networkx as nx
from networkx.algorithms import community
G = nx.karate_club_graph()
comms_greedy = list(community.greedy_modularity_communities(G))
comms_lp = list(community.label_propagation_communities(G))
q_greedy = community.modularity(G, comms_greedy)
q_lp = community.modularity(G, comms_lp)
print(f"Greedy modularity Q = {q_greedy:.4f} ({len(comms_greedy)} communities)")
print(f"Label propagation Q = {q_lp:.4f} ({len(comms_lp)} communities)")- `community.modularity(G, partition)` accepts any list of node sets as the partition, so you can evaluate any external algorithm's output too. - A higher Q means the partition has denser intra-community edges and sparser inter-community edges relative to chance. - Greedy modularity maximizes Q by design, so it will always score at least as well as label propagation on the same graph. Community detection builds on the foundations of graph construction and layout from [NetworkX basics](/tutorials/networkx). To understand which individual nodes are most important within each community, see [centrality measures with NetworkX](/tutorials/centrality-measures-with-networkx).