plot_blockmodel.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. """
  2. ==========
  3. Blockmodel
  4. ==========
  5. Example of creating a block model using the quotient_graph function in NX. Data
  6. used is the Hartford, CT drug users network::
  7. @article{weeks2002social,
  8. title={Social networks of drug users in high-risk sites: Finding the connections},
  9. url = {https://doi.org/10.1023/A:1015457400897},
  10. doi = {10.1023/A:1015457400897},
  11. author={Weeks, Margaret R and Clair, Scott and Borgatti, Stephen P and Radda, Kim and Schensul, Jean J},
  12. journal={{AIDS and Behavior}},
  13. volume={6},
  14. number={2},
  15. pages={193--206},
  16. year={2002},
  17. publisher={Springer}
  18. }
  19. """
  20. from collections import defaultdict
  21. import matplotlib.pyplot as plt
  22. import networkx as nx
  23. import numpy as np
  24. from scipy.cluster import hierarchy
  25. from scipy.spatial import distance
  26. def create_hc(G):
  27. """Creates hierarchical cluster of graph G from distance matrix"""
  28. path_length = nx.all_pairs_shortest_path_length(G)
  29. distances = np.zeros((len(G), len(G)))
  30. for u, p in path_length:
  31. for v, d in p.items():
  32. distances[u][v] = d
  33. # Create hierarchical cluster
  34. Y = distance.squareform(distances)
  35. Z = hierarchy.complete(Y) # Creates HC using farthest point linkage
  36. # This partition selection is arbitrary, for illustrive purposes
  37. membership = list(hierarchy.fcluster(Z, t=1.15))
  38. # Create collection of lists for blockmodel
  39. partition = defaultdict(list)
  40. for n, p in zip(list(range(len(G))), membership):
  41. partition[p].append(n)
  42. return list(partition.values())
  43. G = nx.read_edgelist("hartford_drug.edgelist")
  44. # Extract largest connected component into graph H
  45. H = G.subgraph(next(nx.connected_components(G)))
  46. # Makes life easier to have consecutively labeled integer nodes
  47. H = nx.convert_node_labels_to_integers(H)
  48. # Create partitions with hierarchical clustering
  49. partitions = create_hc(H)
  50. # Build blockmodel graph
  51. BM = nx.quotient_graph(H, partitions, relabel=True)
  52. # Draw original graph
  53. pos = nx.spring_layout(H, iterations=100, seed=83) # Seed for reproducibility
  54. plt.subplot(211)
  55. nx.draw(H, pos, with_labels=False, node_size=10)
  56. # Draw block model with weighted edges and nodes sized by number of internal nodes
  57. node_size = [BM.nodes[x]["nnodes"] * 10 for x in BM.nodes()]
  58. edge_width = [(2 * d["weight"]) for (u, v, d) in BM.edges(data=True)]
  59. # Set positions to mean of positions of internal nodes from original graph
  60. posBM = {}
  61. for n in BM:
  62. xy = np.array([pos[u] for u in BM.nodes[n]["graph"]])
  63. posBM[n] = xy.mean(axis=0)
  64. plt.subplot(212)
  65. nx.draw(BM, posBM, node_size=node_size, width=edge_width, with_labels=False)
  66. plt.axis("off")
  67. plt.show()