社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

利用Python绘制关系网络图

Crossin的编程教室 • 5 年前 • 511 次点击  


大家好,欢迎来到 Crossin的编程教室 !
我们在做数据可视化时,要展现多个元素之间的相互关系时(比如人物关系图),常会用到网络图。
今天我们就分享一个在 Python 里绘制网络图的库:NetworkX,并显示它的基本操作。

一、NetworkX 概述

NetworkX 是一个用 Python 语言开发的图论与复杂网络建模工具,内置了常用的图与复杂网络分析算法,可以方便的进行复杂网络数据分析、仿真建模等工作。
NetworkX 支持创建简单无向图、有向图和多重图;内置许多标准的图论算法,节点可为任意数据;支持任意的边值维度,功能丰富。主要用于创造、操作复杂网络,以及学习复杂网络的结构、动力学及其功能。用于分析网络结构,建立网络模型,设计新的网络算法,绘制网络等等。

二、NetworkX 的安装

  1. pip install networkx -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

三、NetworkX 基础知识

1. 创建图

可以利用 networkx 创建四种图:Graph 、DiGraph、MultiGraph、MultiDiGraph,分别为无多重边无向图、无多重边有向图、有多重边无向图、有多重边有向图。
  1. import network as nx

  2. G = nx.Graph()

  3. G = nx.DiGraph()

  4. G = nx.MultiGraph()

  5. G = nx.MultiDiGraph()

2. 网络图的加点和加边

  1. import networkx as nx

  2. import matplotlib.pyplot as plt


  3. G = nx.DiGraph()

  4. G.add_node('z') # 添加节点z

  5. G.add_nodes_from([1, 2, 3]) # 添加节点 1 2 3

  6. G.add_edge('x', 'y') # 添加边 起点为x 终点为y

  7. G.add_edges_from([(1, 2), (1, 3), (2, 3)]) # 添加多条边


  8. # 网络图绘制与显示

  9. nx.draw(G, with_labels=True)

  10. plt.show()

运行效果如下:
为了让网络图更美观可以调节 nx.draw() 方法里的参数
  1. nx.draw(G, pos=nx.random_layout(G), node_color = 'b', edge_color = 'r', with_labels = True, font_size =18, node_size =20)

  • G:待绘制的网络图G

  • node_size:指定节点的尺寸大小(默认是300)

  • node_color: 指定节点的颜色 (可以用字符串简单标识颜色,例如'r'为红色,'g'为绿色这样)

  • node_shape: 节点的形状(默认是圆形,用字符串'o'标识)

  • alpha: 透明度 (默认是1.0,不透明,0为完全透明)

  • width: 边的宽度 (默认为1.0)

  • edge_color: 边的颜色(默认为黑色)

  • style: 边的样式(默认为实现,可选:solid | dashed | dotted | dashdot

  • with_labels:节点是否带标签

  • font_size: 节点标签字体大小

  • font_color: 节点标签字体颜色(默认为黑色)

3. 运用布局

circular_layout:节点在一个圆环上均匀分布 
random_layout:节点随机分布 
shell_layout:节点在同心圆上分布 
spring_layout:用 Fruchterman-Reingold 算法排列节点(样子类似多中心放射状) 
spectral_layout:根据图的拉普拉斯特征向量排列节点
绘制网络图实例如下:
  1. import networkx as nx

  2. import matplotlib.pyplot as plt


  3. # 初始化一个有向图对象

  4. DG = nx.DiGraph()

  5. DG.add_node('X')

  6. # 添加节点 传入列表

  7. DG.add_nodes_from(['A', 'B', 'C', 'D', 'E'])

  8. print(f'输出图的全部节点:{DG.nodes}')

  9. print(f'输出节点的数量:{DG.number_of_nodes()}')

  10. # 添加边 传入列表 列表里每个元素是一个元组 元组里表示一个点指向另一个点的边

  11. DG.add_edges_from([('A', 'B'), ('A', 'C'), ('A', 'D'), ('D', 'A'), ('E', 'A'), ('E', 'D')])

  12. DG.add_edge('X', 'C')

  13. print(f'输出图的全部边:{DG.edges}')

  14. print(f'输出边的数量:{DG.number_of_edges()}')

  15. # 可自定义节点颜色

  16. colors = ['pink', 'blue', 'green', 'yellow', 'red', 'brown']

  17. # 运用布局

  18. pos = nx.circular_layout(DG)

  19. # 绘制网络图

  20. nx.draw(DG, pos=pos, with_labels=True, node_size=200, width=0.6, node_color=colors)

  21. # 展示图片

  22. plt.show()

运行效果如下:
  1. 输出图的全部节点:['X', 'A', 'B', 'C', 'D', 'E']

  2. 输出节点的数量:6

  3. 输出图的全部边:[('X', 'C'), ('A', 'B'), ('A', 'C'), ('A', 'D'), ('D', 'A'), ('E', 'A'), ('E', 'D')]

  4. 输出边的数量:7

四、利用 NetworkX 实现关联类分析

利用 soccer.csv 中的数据,使用 Python 的 NetworkX 包按要求进行绘图。

1. 提取数据

统计不同俱乐部(Club)的球员数量,从球员最多的五个俱乐部抽取 50 名球员信息(球员数量最多的俱乐部抽取 30 名,剩下 4 个俱乐部各抽取 5 名)构成新的 DataFrame,打印其 info()。
  1. import pandas as pd


  2. df = pd.read_csv('soccer.csv', encoding='gbk')

  3. data = df['Club'].value_counts()

  4. # 球员人数最多的5个俱乐部

  5. clubs = list(data.index[:5])


  6. # 球员数量最多的俱乐部抽取30名

  7. df1 = df[df['Club'] == clubs[0]].sample(30, axis=0)

  8. # 剩下4个俱乐部各抽取5名

  9. df2 = df[df['Club'] == clubs[1]].sample(5, axis=0)

  10. df3 = df[df['Club'] == clubs[2]].sample(5, axis=0)

  11. df4 = df[df['Club'] == clubs[3]].sample( 5, axis=0)

  12. df5 = df[df['Club'] == clubs[4]].sample(5, axis=0)


  13. # 合并多个DataFrame

  14. result = pd.concat([df1, df2, df3, df4, df5], axis=0, ignore_index=True)

  15. # 打乱DataFrame顺序

  16. new_result = result.sample(frac=1).reset_index(drop=True)

  17. # new_result.info()

  18. # 抽样的数据保存到excel

  19. new_result.to_excel('samples.xlsx')

Jupyter Notebook 环境中读取 samples.xlsx,打印其 info(),结果如下:
  1. import pandas as pd


  2. df = pd.read_excel('samples.xlsx')

  3. df.info()

2. 画网络图

在提取出的数据的基础上,通过判断球员是否属于同一俱乐部,绘出随机分布网络图、Fruchterman-Reingold 算法排列节点网络图与同心圆分布网络图。尽可能让网络图美观,如为属于同一俱乐部的节点设置相同的颜色。
将每个球员当作网络图中一个节点,计算节点之间的连通关系,同属一个俱乐部则连通。
  1. import pandas as pd


  2. df = pd.read_excel('samples.xlsx')

  3. df = df.loc[::, ['Name', 'Club']]

  4. print(df['Club'].value_counts())

  5. datas = df.values.tolist()

  6. name = [datas[i][0] for i in range(len(datas))]

  7. nodes = [str(i) for i in range(len(datas))]

  8. club = [datas[i][1] for i in range(len(datas))]

  9. # print(nodes)

  10. df = pd.DataFrame({'姓名': name, '节点编号': nodes, '所属俱乐部': club})

  11. df.to_csv('nodes_info.csv')

  12. with open('record.txt', 'w') as f:

  13. for i in range(len(nodes)):

  14. for j in range(i, len(nodes) - 1):

  15. if datas[i][1] == datas[j+1][1]: # 属于同一俱乐部

  16. f.write(f'{nodes[i]}-{nodes[j + 1]}-{datas[i][1]}'+ '\n')

(1) 随机分布网络图

  1. import networkx as nx

  2. import matplotlib.pyplot as plt

  3. import pandas as pd

  4. from collections importCounter


  5. df = pd.read_csv('nodes_info.csv')['所属俱乐部']

  6. items = df.values

  7. print(Counter(items))

  8. node_colors = []

  9. # 5个俱乐部 属于同一个俱乐部的节点设置相同颜色

  10. for item in items:

  11. if item == 'Free Agents':

  12. node_colors.append('red')

  13. elif item == 'Real Madrid':

  14. node_colors.append('yellow')

  15. elif item == 'Chelsea':

  16. node_colors.append('blue')

  17. elif item == 'FC Barcelona':

  18. node_colors.append('green')

  19. elif item == 'Manchester Utd':

  20. node_colors.append('pink')



  21. DG = nx.MultiGraph()

  22. DG.add_nodes_from([str(i) for i in range(0, 50)])

  23. DG.nodes()


  24. with open('record.txt', 'r') as f:

  25. con = f.read().split('\n')


  26. edges_list = []

  27. for i in con[:-1]:

  28. edges_list.append(tuple(i.split('-')[:2]))


  29. print(edges_list)

  30. DG.add_edges_from(edges_list)


  31. # 运用布局

  32. pos = nx.random_layout(DG) # 节点随机分布

  33. # 绘制网络图

  34. nx.draw(DG, pos, with_labels=True, node_size=200, width=0.6, node_color=node_colors)

  35. # 显示图片

  36. plt.show()

运行效果如下:

(2) Fruchterman-Reingold 算法排列节点网络图

  1. import networkx as nx

  2. import matplotlib.pyplot as plt

  3. import pandas as pd

  4. from collections importCounter


  5. df = pd.read_csv('nodes_info.csv')['所属俱乐部']

  6. items = df.values

  7. print(Counter(items))

  8. node_colors = []

  9. # 5个俱乐部 属于同一个俱乐部的节点设置相同颜色

  10. for item in items:

  11. if item == 'Free Agents':

  12. node_colors.append('red')

  13. elif item == 'Real Madrid':

  14. node_colors.append('yellow')

  15. elif item == 'Chelsea':

  16. node_colors.append('blue')

  17. elif item == 'FC Barcelona':

  18. node_colors.append('green')

  19. elif item == 'Manchester Utd':

  20. node_colors.append('pink')


  21. DG = nx.MultiGraph()

  22. DG.add_nodes_from([str(i) for i in range(0, 50)])

  23. DG.nodes()


  24. with open('record.txt', 'r') as f:

  25. con = f.read().split('\n')


  26. edges_list = []

  27. for i in con[:-1]:

  28. edges_list.append(tuple(i.split('-')[:2]))


  29. print(edges_list)

  30. DG.add_edges_from(edges_list)


  31. # 运用布局

  32. pos = nx.spring_layout(DG) # 用Fruchterman-Reingold算法排列节点(样子类似多中心放射状)

  33. # 绘制网络图

  34. nx.draw(DG, pos, node_size=10, width=0.6, node_color=node_colors)

  35. # 显示图片

  36. plt.show()

运行效果如下:

(3) 同心圆分布网络图

  1. import networkx as nx

  2. import matplotlib.pyplot as plt

  3. import pandas as pd

  4. from collections importCounter


  5. df = pd.read_csv('nodes_info.csv')['所属俱乐部']

  6. items = df.values

  7. print(Counter(items))

  8. node_colors = []

  9. # 5个俱乐部 属于同一个俱乐部的节点设置相同颜色

  10. for item in items:

  11. if item == 'Free Agents':

  12. node_colors.append('red')

  13. elif item == 'Real Madrid':

  14. node_colors.append('yellow')

  15. elif item == 'Chelsea':

  16. node_colors.append('blue')

  17. elif item == 'FC Barcelona':

  18. node_colors.append('green')

  19. elif item == 'Manchester Utd':

  20. node_colors.append('pink')


  21. DG = nx.MultiGraph()

  22. DG.add_nodes_from([str(i) for i in range(0, 50)])

  23. DG.nodes()


  24. with open('record.txt', 'r') as f:

  25. con = f.read().split('\n')


  26. edges_list = []

  27. for i in con[:-1]:

  28. edges_list.append(tuple(i.split('-')[:2]))


  29. print(edges_list)

  30. DG.add_edges_from(edges_list)


  31. # 运用布局

  32. pos = nx.shell_layout(DG) # 节点在同心圆上分布

  33. # 绘制网络图

  34. nx.draw(DG, pos, with_labels=True, node_size=200, width=0.6, node_color=node_colors)

  35. # 显示图片

  36. plt.show()

运行效果如下:
以上就是利用 NetworkX 绘制关系网络图的常用方法。
本文的数据和代码:
https://306t.com/file/23159928-465081046

如果文章对你有帮助,欢迎转发/点赞/收藏~

作者:叶庭云
博客:https://blog.csdn.net/fyfugoyfa/
编辑:Lemon
来源:Python数据之道


_往期文章推荐_

绘制漫威人物关系图




如需了解付费精品课程及教学答疑服务
请在Crossin的编程教室内回复: 666

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/114655