目录
一、前言
二、建模工具库Networkx的下载安装
三、规则图
四、ER随机图
五、WS小世界网络
六、BA无标度网络
七、补充
参考文献
最近用Python实现了四种网络模型(规则图,ER随机图,WS小世界网络和BA无标度网络)的复现,具体内容为使用建模工具库Networkx实现网络模型的生成,平均度、最短路径长度、聚类系数等指标的计算,及度分布函数的计算和展示。
根据查询网上资料,我总结了一些方法,也产生了一些心得体会,呈现如下:
Python中有一个库叫做NetworkX,其提供了4种常见网络的建模方法,分别是:规则图,ER随机图,WS小世界网络和BA无标度网络。下载该库后,生成网络模型就变得较为容易了。
直接pip install Networkx的话会特别慢,而且通常会失败,所以建议先把库下载下来,再在本地安装。
1. 下载地址:https://pypi.org/project/networkx/#files
2. 放到自己指定的文件夹(随意)
3. cmd-输入指令安装:pip install 文件路径,如:
pip install D:\Study\networkX\networkx-2.8.8-py3-none-any.whl
1. 调用函数名:random_graphs.random_regular_graph(d, n)
2. 作用:生成一个包含n个节点、每个节点有d个邻居的规则图
3. 代码示例:
import networkx as nx
import matplotlib.pyplot as plt
# 生成了包含20个节点、每个节点有3个邻居的规则图
G = nx.random_graphs.random_regular_graph(3, 10)
# shell布局
pos = nx.shell_layout(G)
# 画出网络模型
nx.draw(G, pos, with_labels = False, node_size = 30)
# 获取各节点与相应度值的字典
degree = dict(nx.degree(G))
# 平均度为所有节点度之和除以总节点数
print("平均度为:", sum(degree.values())/len(G))
# 最短路径长度
print("最短路径长度为:",nx.average_shortest_path_length(G))
# 平均集类系数
print("平均聚类系数为:",nx.average_clustering(G))
# 获取度分布,返回所有位于区间[0, dmax]的度值的频数列表
degreeDis = nx.degree_histogram(G)
x = range(len(degreeDis)) # 生成X轴序列,从1到最大度
y = [z / float(sum(degreeDis)) for z in degreeDis] # 将频次转化为频率
plt.figure(figsize=(5.8, 5.2), dpi=150) # 调整显示参数
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.xlabel("Degree", size=14) # Degree
plt.ylabel("Frequency", size=14) # Frequency
plt.xticks(fontproperties='Times New Roman', size=13) # 字体样式
plt.yticks(fontproperties='Times New Roman', size=13) # 字体样式
plt.plot(x,y) # 折线图
plt.show() # 显示图像
4. 输出结果:
1. 调用函数名:random_graphs.erdos_renyi_graph(n,p)
2. 作用:生成一个含有n个节点、以概率p连接的ER随机图
3. 代码示例:
import networkx as nx
import matplotlib.pyplot as plt
# 生成一个含有20个节点、以概率p = 0.2连接的ER随机图:
G = nx.random_graphs.erdos_renyi_graph(20, 0.2)
# shell布局
pos = nx.shell_layout(G)
# 画出网络模型
nx.draw(G, pos, with_labels = False, node_size = 30)
# 获取各节点与相应度值的字典
degree = dict(nx.degree(G))
# 平均度为所有节点度之和除以总节点数
print("平均度为:", sum(degree.values())/len(G))
# 最短路径长度
print("最短路径长度为:",nx.average_shortest_path_length(G))
# 平均集类系数
print("平均聚类系数为:",nx.average_clustering(G))
# 获取度分布,返回所有位于区间[0, dmax]的度值的频数列表
degreeDis = nx.degree_histogram(G)
x = range(len(degreeDis)) # 生成X轴序列,从1到最大度
y = [z / float(sum(degreeDis)) for z in degreeDis] # 将频次转化为频率
plt.figure(figsize=(5.8, 5.2), dpi=150) # 调整显示参数
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.xlabel("Degree", size=14) # Degree
plt.ylabel("Frequency", size=14) # Frequency
plt.xticks(fontproperties='Times New Roman', size=13) # 字体样式
plt.yticks(fontproperties='Times New Roman', size=13) # 字体样式
plt.plot(x,y) # 折线图
plt.show() # 显示图像
4. 输出结果:
1. 调用函数名:random_graphs.watts_strogatz_graph(n, k, p)
2. 作用:生成一个含有n个节点、每个节点有k个邻居、以概率p随机化重连边的WS小世界网络
3. 代码示例:
import networkx as nx
import matplotlib.pyplot as plt
# 生成一个含有20个节点、每个节点有4个邻居、以概率p=0.3随机化重连边的WS小世界网络
G = nx.random_graphs.watts_strogatz_graph(20, 4, 0.3)
# circular布局
pos = nx.circular_layout(G)
nx.draw(G, pos, with_labels = False, node_size = 30)
# 获取各节点与相应度值的字典
degree = dict(nx.degree(G))
# 平均度为所有节点度之和除以总节点数
print("平均度为:", sum(degree.values())/len(G))
# 最短路径长度
print("最短路径长度为:",nx.average_shortest_path_length(G))
# 平均集类系数
print("平均聚类系数为:",nx.average_clustering(G))
# 获取度分布,返回所有位于区间[0, dmax]的度值的频数列表
degreeDis = nx.degree_histogram(G)
x = range(len(degreeDis)) # 生成X轴序列,从1到最大度
y = [z / float(sum(degreeDis)) for z in degreeDis] # 将频次转化为频率
plt.figure(figsize=(5.8, 5.2), dpi=150) # 调整显示参数
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.xlabel("Degree", size=14) # Degree
plt.ylabel("Frequency", size=14) # Frequency
plt.xticks(fontproperties='Times New Roman', size=13) # 字体样式
plt.yticks(fontproperties='Times New Roman', size=13) # 字体样式
plt.plot(x,y) # 折线图
plt.show() # 显示图像
4. 输出结果:
1. 调用函数名:random_graphs.barabasi_albert_graph(n, m)
2. 作用:生成一个含有n个节点、每次加入m条边的BA无标度网络
3. 代码示例:
import networkx as nx
import matplotlib.pyplot as plt
# 生成一个含有20个节点、每次加入1条边的BA无标度网络。
G = nx.random_graphs.barabasi_albert_graph(20, 1)
# spring 布局
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels = False, node_size = 30)
# 获取各节点与相应度值的字典
degree = dict(nx.degree(G))
# 平均度为所有节点度之和除以总节点数
print("平均度为:", sum(degree.values())/len(G))
# 最短路径长度
print("最短路径长度为:",nx.average_shortest_path_length(G))
# 平均集类系数
print("平均聚类系数为:",nx.average_clustering(G))
# 获取度分布,返回所有位于区间[0, dmax]的度值的频数列表
degreeDis = nx.degree_histogram(G)
x = range(len(degreeDis)) # 生成X轴序列,从1到最大度
y = [z / float(sum(degreeDis)) for z in degreeDis] # 将频次转化为频率
plt.figure(figsize=(5.8, 5.2), dpi=150) # 调整显示参数
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.xlabel("Degree", size=14) # Degree
plt.ylabel("Frequency", size=14) # Frequency
plt.xticks(fontproperties='Times New Roman', size=13) # 字体样式
plt.yticks(fontproperties='Times New Roman', size=13) # 字体样式
#plt.loglog(x, y, '.') # 对数化坐标
plt.plot(x,y) # 折线图
plt.show() # 显示图像
4. 输出结果:
5. 幂律分布
另外,我还想测试一下BA网络的度分布是否真的呈现为幂律分布,因此尝试将函数random_graphs.barabasi_albert_graph(n, m)中的参数调整为100000,3;并将度分布对数化。因为数据量过大,网络模型画出来也会是乌黑黑一坨,因此干脆直接注释掉。
代码如下:
import networkx as nx
import matplotlib.pyplot as plt
# 生成一个含有100000个节点、每次加入3条边的BA无标度网络。
G = nx.random_graphs.barabasi_albert_graph(100000, 3)
# spring 布局
#pos = nx.spring_layout(G)
#nx.draw(G, pos, with_labels = False, node_size = 30)
# 获取各节点与相应度值的字典
#degree = dict(nx.degree(G))
# 平均度为所有节点度之和除以总节点数
#print("平均度为:", sum(degree.values())/len(G))
# 最短路径长度
#print("最短路径长度为:",nx.average_shortest_path_length(G))
# 平均集类系数
#print("平均聚类系数为:",nx.average_clustering(G))
# 获取度分布,返回所有位于区间[0, dmax]的度值的频数列表
degreeDis = nx.degree_histogram(G)
x = range(len(degreeDis)) # 生成X轴序列,从1到最大度
y = [z / float(sum(degreeDis)) for z in degreeDis] # 将频次转化为频率
plt.figure(figsize=(5.8, 5.2), dpi=150) # 调整显示参数
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.xlabel("Degree", size=14) # Degree
plt.ylabel("Frequency", size=14) # Frequency
plt.xticks(fontproperties='Times New Roman', size=13) # 字体样式
plt.yticks(fontproperties='Times New Roman', size=13) # 字体样式
plt.loglog(x, y, '.') # 对数化坐标
#plt.plot(x,y) # 折线图
plt.show() # 显示图像
然后就出现了下面这样的报错:
根据查询资料发现报错原因是缺少名为“scipy”的包,因此尝试通过在cmd输入pip install scipy指令下载,但还是报错:
最后通过这条指令才成功下载:
pip install scipy -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
输出结果如下:
1. 运用样式
NetworkX提供了一系列样式参数,可以用来修饰和美化图形,达到我们想要的效果。常用的参数包括:
- node_size: 指定节点的尺寸大小(默认是300,单位未知,就是上图中那么大的点)
- node_color: 指定节点的颜色 (默认是红色,可以用字符串简单标识颜色,例如’r’为红色,'b’为绿色等,具体可查看手册)
- node_shape: 节点的形状(默认是圆形,用字符串’o’标识,具体可查看手册)
- alpha: 透明度 (默认是1.0,不透明,0为完全透明)
- width: 边的宽度 (默认为1.0)
- edge_color: 边的颜色(默认为黑色)
- style: 边的样式(默认为实现,可选: solid|dashed|dotted,dashdot)
- with_labels: 节点是否带标签(默认为True)
- font_size: 节点标签字体大小 (默认为12)
- font_color: 节点标签字体颜色(默认为黑色)
灵活运用上述参数,可以绘制不同样式的网络图形,例如:nx.draw(G,node_size = 30,with_labels = False) 是绘制节点尺寸为30、不带标签的网络图。
2. 运用布局
NetworkX在绘制网络图形方面提供了布局的功能,可以指定节点排列的形式。这些布局包括:
circular_layout:节点在一个圆环上均匀分布
random_layout:节点随机分布
shell_layout:节点在同心圆上分布
spring_layout: 用Fruchterman-Reingold算法排列节点
spectral_layout:根据图的拉普拉斯特征向量排列节点
布局用pos参数指定,例如:nx.draw(G,pos = nx.circular_layout(G))
图论与复杂网络建模工具Networkx的四种网络模型_JYeeYao的博客-CSDN博客_random_graphs.watts_strogatz_graph(n, k, p)
复杂网络_JasonYangQ的博客-CSDN博客
复杂网络度分布(幂律分布)图Python_Morty Ma的博客-CSDN博客_网络度分布
解决pip安装包时出现 WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None))_cicoa的博客-CSDN博客_c:\users\gaoying>pip install scipy warning: retryi