更多内容请查看官方文档,以下内容参考
https://networkx.github.io/
networkX是一个Python包,用于创建、操作和研究复杂网络的结构、动态和功能。
安装只需在控制台使用pip安装即可,问题不大。
pip install networkx
不过复杂网络毕竟还是要可视化的,这边建议您同时使用python图形库matplotlib
import networkx as nx
import matplotlib.pyplot as plt
根据图的定义,图是节点的集合,并且节点间有依赖关系(边)。
在NetworkX中,节点可以是任何可刷新的对象,如文本字符串、图像、XML对象、另一个图(Graph)、自定义节点对象等。
使用如下代码,即可生成一个图。
G = nx.Graph()
使用如下代码,即可生成包含三个节点的图,当然没有边连接的图就看起来特别搞笑。
import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph() #生成图
G.add_node(1) #添加一个节点
G.add_nodes_from([2, 3]) #添加列表里的节点
#可视化
nx.draw(G)
plt.show()
直接定义边连接,无需重新定义节点。
import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph() #生成图
G.add_edge(1, 2) #添加一条边
G.add_edges_from([(1, 3), (2, 3)]) #添加列表里的边
#可视化
nx.draw(G)
plt.show()
如下代码可以为图、节点、边添加属性信息。
import networkx as nx
import matplotlib.pyplot as plt
#为图添加属性
G = nx.Graph(day="Friday")
print(G.graph)
#为节点添加属性
G.add_node(1, time='5pm')
G.add_nodes_from([3], time='2pm')
print(G.nodes[1])
G.nodes[1]['room'] = 714
print(G.nodes.data())
#为边添加属性
G.add_edges_from([(1, 2), (1, 3)])
print(G.edges[1, 2])
G.edges[1, 2]['color'] = "red" #为边添加属性
print(G.edges[1, 2])
>>> {'day': 'Friday'}
>>> {'time': '5pm'}
>>> NodeDataView({1: {'time': '5pm', 'room': 714}, 3: {'time': '2pm'}})
>>> {}
>>> {'color': 'red'}
当添加新的节点、边时,networkx会忽略任何已经存在的节点、边。
import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph()
G.add_edges_from([(1, 2), (1, 3)])
G.add_node(1)
G.add_edge(1, 2)
G.add_node("spam") # 添加节点"spam"
G.add_nodes_from("spam") # 添加四个节点: 's', 'p', 'a', 'm'
G.add_edge(3, 'm')
nx.draw(G , with_labels=True, font_weight='bold') #显示标签,字体加粗
plt.show()
同时也可以输出图中节点和边的数量等信息。
>>> G.number_of_nodes()
8
>>> G.number_of_edges()
3
>>> list(G.nodes)
[1, 2, 3, 'spam', 's', 'p', 'a', 'm']
>>> list(G.edges)
[(1, 2), (1, 3), (3, 'm')]
>>> list(G.adj[1]) # 或 list(G.neighbors(1)) , 输出节点 1 的关联节点
[2, 3]
>>> G.degree[1] # 无向图中节点 1 的度,也就是该节点关联节点的数量,也可以理解成连接边数量
2
在图中删除节点与连边
>>> G.remove_node(2)
>>> G.remove_nodes_from("spam")
>>> G.remove_edge(1, 3)
>>>> list(G.nodes)
[1, 3, 'spam']
遍历操作是特别重要的,G.adjacency()和G.adj.items()可以对图快速遍历。
不过需要注意的是,对于无向图而言,迭代会看到每条边两次。
>>> FG = nx.Graph()
>>> FG.add_weighted_edges_from([(1, 2, 0.125), (1, 3, 0.75), (2, 4, 1.2), (3, 4, 0.375)])
>>> for n, nbrs in FG.adj.items():
... for nbr, eattr in nbrs.items():
... wt = eattr['weight']
... if wt < 0.5: print('(%d, %d, %.3f)' % (n, nbr, wt))
(1, 2, 0.125)
(2, 1, 0.125)
(3, 4, 0.375)
(4, 3, 0.375)
通过边线属性可以方便地访问符合权重小于0.5的边。
>>> for (u, v, wt) in FG.edges.data('weight'):
... if wt < 0.5: print('(%d, %d, %.3f)' % (u, v, wt))
(1, 2, 0.125)
(3, 4, 0.375)
有向图就需要指定权重,并且节点会有出度值以及入度值。
import networkx as nx
import matplotlib.pyplot as plt
DG = nx.DiGraph()
DG.add_weighted_edges_from([(1, 2, 0.5), (3, 1, 0.75)])
print(DG.in_degree(1, weight='weight')) #节点1的入度值
print(DG.out_degree(1, weight='weight')) #节点1的出度值
print(DG.degree(1, weight='weight')) #节点1的度
>>> 0.75
>>> 0.5
>>> 1.25
除了按节点构建图或按边构建图外,还可以通过其他方法生成图。
例如生成一个神秘的阵法。
import networkx as nx
import matplotlib.pyplot as plt
G = nx.dodecahedral_graph() #十二面体?
options = {
'node_color': 'black',
'node_size': 100,
'width': 3,
}
shells = [[2, 3, 4, 5, 6], [8, 1, 0, 19, 18, 17, 16, 15, 14, 7], [9, 10, 11, 12, 13]]
nx.draw_shell(G, nlist=shells , **options)
plt.show()
都是一些骚操作,在此不做展开。
感兴趣请访问https://networkx.github.io/documentation/stable/tutorial.html#graph-generators-and-graph-operations
以Wiki vote投票网络学习复杂网络基本名词以及networkx包对复杂网络进行基本操作,并通过随机ER图、SW小世界图和真实的合作网络数据集为例,学习网络的基本分析方法。
数据来源 Wiki投票数据
import networkx as nx
import matplotlib.pyplot as plt
G = nx.DiGraph()
#读取数据
with open('Wiki-Vote.txt') as f:
for line in f:
if len(line.split()) > 2: #txt文件中前面四行是注释信息
continue #该判断语句作用是过滤掉前四行
data_line = line.split()
G.add_edge(data_line[0], data_line[1])
print('网络中的节点数量:%d'%nx.number_of_nodes(G))
#有没有自己投票给自己的
print('网络有自环的节点数量:%d'%nx.number_of_selfloops(G))
#既然没有自环节点,那有向边数量就是所有边的数量
print('网络中有向边数量:%d'%G.number_of_edges())
#有多少对节点互相投票
count = 0
for x in G.edges:
if (x[1],x[0]) in G.edges:
count += 1
print('网络中互惠边数量:%d'%(count//2))
#计算入度和出度为 0 的节点
count = 0
for x in G.in_degree():
if x[1] != 0:
count += 1
print('网络入度为 0 的节点:%d'%(count))
count = 0
for x in G.out_degree():
if x[1] != 0:
count += 1
print('网络出度为 0 的节点:%d'%(count))
#计算入度和出度大于 10 的节点
count = 0
for x in G.in_degree():
if x[1] < 10:
count += 1
print('网络入度小于 10 的节点:%d'%(count))
count = 0
for x in G.out_degree():
if x[1] > 10:
count += 1
print('网络出度大于 10 的节点:%d'%(count))
输出
网络中的节点数量:7115
网络有自环的节点数量:0
网络中有向边数量:103689
网络中互惠边数量:2927
网络入度为 0 的节点:2381
网络出度为 0 的节点:6110
网络入度小于 10 的节点:5165
网络出度大于 10 的节点:1612
此为本人两年前复杂网络课程作业,本人并没有仔细关注有些计算是否有对应的方法,因此一些计算采用了迭代的方式算出结果,欢迎指正。
通过调用以下方法实现
gnm_random_graph(n, k ,seed , directed=True]) |
---|
返回随机图 |
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
#生成n=5242个节点以及m=14484条边的有向随机图。
n = 5242
m = 14484
G1 = nx.gnm_random_graph (n,m, seed = 7 ,directed = True)
nx.draw(G1,node_size=70)
plt.show()
通过调用以下方法实现
watts_strogatz_graph(n, k, p[, seed]) |
---|
返回Watts–Strogatz小世界图 |
通过nx.watts_strogatz_graph(5242, 4, p=0, seed = 7)方法生成一个节点为5242的有向图,每个节点与相邻最近的4个节点相连,与其他节点相连的概率为0,随机种子为7,通过pos布局设置为环状。
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
n = 5242
k = 4
G = nx.watts_strogatz_graph(n, k, p=0, seed = 7)
pos = nx.circular_layout(G,scale = 1,center = None,dim = 2 )
print("sw小世界边数为:" , nx.number_of_edges(G))
来源 https://github.com/kjahan/community
算法原理省略,社区检测算法可以简单理解为聚类。
python cmty.py graph.txt
Max modularity (Q): 0.0183279215837773
Graph communities: [{0}, {1, 65, 66, 68, 45, 17, 30, 54, 22, 56, 57, 26, 24, 31}, {14}, {9, 11, 21, 25, 28, 29, 32, 37, 41, 43, 44, 51, 53, 55, 58, 59, 61, 63, 70, 72}, {48, 50}, {52}, {2}, {3}, {34, 4, 5}, {19, 7}, {16}, {18}, {20}, {27}, {35}, {39}, {42}, {47}, {49}, {62}, {67}, {69}, {71}, {73}, {6}, {12}, {13}, {15}, {33}, {38}, {40}, {60}, {64}, {8}, {10}, {23}, {36}, {46}, {74}]
友情提示:仔细阅读官方文档,提高编程能力,不行全问别人,除非给买好吃的。