networkX构建图学习笔记

0.前言

本文章主要记录笔者在写毕业设计时的东西,便于以后回顾时能够快速明白自己当年写的是什么,同时也给予一些读者思路或灵感什么的。

因为笔者实力有限,可能内容会有部分错误或者有更好的方法却未使用,请不要多怪指责。

1.networkx

先来简单讲解一下networkx的构建图的一些基本用法

导库

1
import networkx as nx

无向图

创建空的图

1
G = nx.Graph()

添加节点

1
2
G.add_node('a')
G.add_node_from(['a','b'])

第一个添加的是一个一个的节点,节点可以是字符串也可以是数字。

第二个添加的是列表,即可以添加一个一个的节点,也可以将一个列表的节点添加进去。

如果想对节点添加一些属性,可以使用以下的方法(例子是添加用户名这个属性)

1
2
G.add_node('a',user_name='blue')
G.add_nodes_from([3], user_name='blue')

同样也可以对空的图添加属性

1
G=nx.Graph(day="Friday")

添加边

1
2
G.add_edge('a','b',user_name="blue")
G.add_edges_from([('a','b',{"user_name":"blue"})])

以上两种方法都是在a,b两个节点间建立一条边,后面的参数是添加边的属性。

第一种是一条边一条边的添加,第二种是可以一条一条或者一个列表地添加边。

查看节点属性

1
2
isCore = nx.get_node_attributes(G, 'user_name')
print(isCore['b'])

查看边属性

1
2
isCore = nx.get_edge_attributes(G,'user_name')
print(isCore)

给边添加权重

1
2
G.add_weighted_edges_from([('a','b',1)])
print(G.get_edge_data('a','b'))

其中get_edge_data()方法是用来查看边的属性的(权重的属性名为weight,如果添加了其他属性在里面,它会全部显示出来。)

其他的查看

1
2
3
print(G.number_of_edges())   #查看边的数量
print(G.nodes()) #查看G图的全部节点
print(G.edges()) #查看G图的全部边

其他一些函数

nx.degree(G)#计算图的密度,其值为边数m除以图中可能边数(即n(n-1)/2)

nx.degree_centrality(G)#节点度中心系数。通过节点的度表示节点在图中的重要性,默认情况下会进行归一化,其值表达为节点度d(u)除以n-1(其中n-1就是归一化使用的常量)。这里由于可能存在循环,所以该值可能大于1.

nx.closeness_centrality(G)#节点距离中心系数。通过距离来表示节点在图中的重要性,一般是指节点到其他节点的平均路径的倒数,这里还乘以了n-1。该值越大表示节点到其他节点的距离越近,即中心性越高。

nx.betweenness_centrality(G)#节点介数中心系数。在无向图中,该值表示为节点作占最短路径的个数除以((n-1)(n-2)/2);在有向图中,该值表达为节点作占最短路径个数除以((n-1)(n-2))。

nx.transitivity(G)#图或网络的传递性。即图或网络中,认识同一个节点的两个节点也可能认识双方,计算公式为3*图中三角形的个数/三元组个数(该三元组个数是有公共顶点的边对数,这样就好数了)。

nx.clustering(G)#图或网络中节点的聚类系数。计算公式为:节点u的两个邻居节点间的边数除以((d(u)(d(u)-1)/2)。

有向图

有向图的建立和添加跟无向图几乎一模一样,只要理解了什么是有向图和无向图,基本上这方面不成问题。唯一要注意的是有向图的建立跟无向图不一样,下面给出代码

1
G = nx.DiGraph()

画图

1
2
3
import matplotlib.pyplot as plt
nx.draw(G, pos=nx.circular_layout(G),with_labels=True)
plt.show()

2.通过数据生成无向图并添加权重

生成无向图和添加权重通过上面的介绍就可以实现了,唯一存在的问题是csv库的读取方法reader()存在无法重复循环的问题,例子如下

1
2
3
4
5
6
7
8
with open(filename, 'r', encoding='utf-8') as file:
next(file) #用于跳过第一行
fLine = csv.reader(file)
for i in fLine:
print("yes")
for j in fLine:
print("no")
file.close()

输出如下(假设除去第一行只有三行数据):

1
2
3
4
yes
no
no
no

之所以输出是这样,是因为这个reader()方法读取完文件的数据后就会自动关掉文件,导致无法进行第二次循环。

所以我们改用numpy库来提取数据

np库方法

1
2
3
with open(filename, 'r', encoding='utf-8') as file:
data2 = np.loadtxt(file, str, delimiter=",", skiprows=1) #参数为文件、支持str类型,以,为分隔符,跳过第一行
file.close()

PS:之所以不用python自带的readlines()等方法是因为提取出来的数据是字符串,要弄成列表形式还要进一步的处理,所以直接pass掉。