plot_blockmodel.py 2.8 KB

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