{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n# Blockmodel\n\nExample of creating a block model using the quotient_graph function in NX. Data\nused is the Hartford, CT drug users network::\n\n @article{weeks2002social,\n title={Social networks of drug users in high-risk sites: Finding the connections},\n url = {https://doi.org/10.1023/A:1015457400897},\n doi = {10.1023/A:1015457400897},\n author={Weeks, Margaret R and Clair, Scott and Borgatti, Stephen P and Radda, Kim and Schensul, Jean J},\n journal={{AIDS and Behavior}},\n volume={6},\n number={2},\n pages={193--206},\n year={2002},\n publisher={Springer}\n }\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from collections import defaultdict\n\nimport matplotlib.pyplot as plt\nimport networkx as nx\nimport numpy as np\nfrom scipy.cluster import hierarchy\nfrom scipy.spatial import distance\n\n\ndef create_hc(G):\n \"\"\"Creates hierarchical cluster of graph G from distance matrix\"\"\"\n path_length = nx.all_pairs_shortest_path_length(G)\n distances = np.zeros((len(G), len(G)))\n for u, p in path_length:\n for v, d in p.items():\n distances[u][v] = d\n # Create hierarchical cluster\n Y = distance.squareform(distances)\n Z = hierarchy.complete(Y) # Creates HC using farthest point linkage\n # This partition selection is arbitrary, for illustrative purposes\n membership = list(hierarchy.fcluster(Z, t=1.15))\n # Create collection of lists for blockmodel\n partition = defaultdict(list)\n for n, p in zip(list(range(len(G))), membership):\n partition[p].append(n)\n return list(partition.values())\n\n\nG = nx.read_edgelist(\"hartford_drug.edgelist\")\n\n# Extract largest connected component into graph H\nH = G.subgraph(next(nx.connected_components(G)))\n# Makes life easier to have consecutively labeled integer nodes\nH = nx.convert_node_labels_to_integers(H)\n# Create partitions with hierarchical clustering\npartitions = create_hc(H)\n# Build blockmodel graph\nBM = nx.quotient_graph(H, partitions, relabel=True)\n\n# Draw original graph\npos = nx.spring_layout(H, iterations=100, seed=83) # Seed for reproducibility\nplt.subplot(211)\nnx.draw(H, pos, with_labels=False, node_size=10)\n\n# Draw block model with weighted edges and nodes sized by number of internal nodes\nnode_size = [BM.nodes[x][\"nnodes\"] * 10 for x in BM.nodes()]\nedge_width = [(2 * d[\"weight\"]) for (u, v, d) in BM.edges(data=True)]\n# Set positions to mean of positions of internal nodes from original graph\nposBM = {}\nfor n in BM:\n xy = np.array([pos[u] for u in BM.nodes[n][\"graph\"]])\n posBM[n] = xy.mean(axis=0)\nplt.subplot(212)\nnx.draw(BM, posBM, node_size=node_size, width=edge_width, with_labels=False)\nplt.axis(\"off\")\nplt.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.7"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Generated by dwww version 1.16 on Fri Apr 10 10:44:18 CEST 2026.