在看graph RNN源代码发现他用了这个库。
1.1、Graph
1.1.1、Graph的定义
Graph是用点和线来刻画离散事物集合中的每对事物间以某种方式相联系的数学模型。
网络作为图的一个重要领域,包含的概念与定义更多,如有向图网络(Directed Graphs and Networks)、无向图网络(Undirected)等概念。
Graph在现实世界中随处可见,如交通运输图、旅游图、流程图等。此处我们只考虑由点和线所组成的图。
利用图可以描述现实生活中的许多事物,如用点可以表示交叉口,点之间的连线表示路径,这样就可以轻而易举的描绘出一个交通运输网络。
1.1.2、Graph的结构
根据Graph的定义,一个Graph包含一个节点集合和一个边集。
在NetworkX中,一个节点可以是任意hash对象(除了None对象),一条边也可以关联任意的对象,像一个文本字符串,一幅图像,一个XML对象,甚至是另一个图或任意定制的节点对象。
注意:Python中的None对象是不可以作为节点的类型的。
节点与边能够存储任意类型字典的属性和任意其他丰富类型的数据。
1.1.3、Graph分类
- Graph:指无向图(undirected Graph),即忽略了两节点间边的方向。
- DiGraph:指有向图(directed Graph),即考虑了边的有向性。
- MultiGraph:指多重无向图,即两个结点之间的边数多于一条,又允许顶点通过同一条边和自己关联。
- MultiDiGraph:多重图的有向版本。
G = nx.Graph() # 创建无向图 G = nx.DiGraph() # 创建有向图 G = nx.MultiGraph() # 创建多重无向图 G = nx.MultiDigraph() # 创建多重有向图 G.clear() #清空图
2、基本操作
2.1、无向图
- 节点 如果添加的节点和边是已经存在的,是不会报错的,NetworkX会自动忽略掉已经存在的边和节点的添加。
import networkx as nx
import matplotlib.pyplot as plt
plt.switch_backend('agg')
G = nx.Graph() #建立一个空的无向图G
G.add_node('a') #添加一个节点1
nx.draw(G, with_labels=True)
plt.show()#显示一个点a
G.add_nodes_from(['b','c','d','e']) #加点集合
nx.draw(G, with_labels=True)
plt.show()
G.add_cycle(['f','g','h','j']) #加环
nx.draw(G, with_labels=True)
plt.show()
H = nx.path_graph(10)
G.add_node(H) #直接将图作为节点
nx.draw(G, with_labels=True)
plt.show()
G.add_cycle(['ff','fg','fh','fj']) #加环
nx.draw(G, with_labels=True)
plt.show()
H = nx.path_graph(10) #返回由10个节点挨个连接的无向图,所以有9条边
G.add_nodes_from(H) #创建一个子图H加入G
nx.draw(G, with_labels=True)
plt.show()
#访问节点
print('图中所有的节点', G.nodes())
print('图中节点的个数', G.number_of_nodes())
#删除节点
G.remove_node(1) #删除指定节点
G.remove_nodes_from(['b','c','d','e']) #删除集合中的节点
nx.draw(G, with_labels=True)
plt.show()
#添加边
F = nx.Graph() # 创建无向图
F.add_edge(11,12) #一次添加一条边
#等价于
e=(13,14) #e是一个元组
F.add_edge(*e) #这是python中解包裹的过程
F.add_edges_from([(1,2),(1,3)]) #通过添加list来添加多条边
#通过添加任何ebunch来添加边
F.add_edges_from(H.edges()) #不能写作F.add_edges_from(H)
nx.draw(F, with_labels=True)
plt.show()
#访问边
print('图中所有的边', F.edges())
print('图中边的个数', F.number_of_edges())
#快速遍历每一条边,可以使用邻接迭代器实现,对于无向图,每一条边相当于两条有向边
FG = nx.Graph()
FG.add_weighted_edges_from([(1,2,0.125), (1,3,0.75), (2,4,1.2), (3,4,0.275)])
for n, nbrs in FG.adjacency():
for nbr, eattr in nbrs.items():
data = eattr['weight']
print('(%d, %d, %0.3f)' % (n,nbr,data))
print('***********************************')
#筛选weight小于0.5的边:
FG = nx.Graph()
FG.add_weighted_edges_from([(1,2,0.125), (1,3,0.75), (2,4,1.2), (3,4,0.275)])
for n, nbrs in FG.adjacency():
for nbr, eattr in nbrs.items():
data = eattr['weight']
if data < 0.5:
print('(%d, %d, %0.3f)' % (n,nbr,data))
print('***********************************')
#一种方便的访问所有边的方法:
for u,v,d in FG.edges(data = 'weight'):
print((u,v,d))
#删除边
F.remove_edge(1,2)
F.remove_edges_from([(11,12), (13,14)])
nx.draw(F, with_labels=True)
plt.show()
- 属性
属性诸如weight,labels,colors,或者任何对象,你都可以附加到图、节点或边上。
对于每一个图、节点和边都可以在关联的属性字典中保存一个(多个)键-值对。
默认情况下这些是一个空的字典,但是我们可以增加或者是改变这些属性。
#图的属性
import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph(day='Monday') #可以在创建图时分配图的属性
print(G.graph)
G.graph['day'] = 'Friday' #也可以修改已有的属性
print(G.graph)
G.graph['name'] = 'time' #可以随时添加新的属性到图中
print(G.graph)
#节点的属性
G = nx.Graph(day='Monday')
G.add_node(1, index='1th') #在添加节点时分配节点属性
print(G.node(data=True))
G.node[1]['index'] = '0th' #通过G.node[][]来添加或修改属性
print(G.node(data=True))
G.add_nodes_from([2,3], index='2/3th') #从集合中添加节点时分配属性
print(G.nodes(data=True))
print(G.node(data=True))
#边的属性
G = nx.Graph(day='manday')
G.add_edge(1,2,weight=10) #在添加边时分配属性
print(G.edges(data=True))
G.add_edges_from([(1,3), (4,5)], len=22) #从集合中添加边时分配属性
print(G.edges(data='len'))
G.add_edges_from([(3,4,{'hight':10}),(1,4,{'high':'unknow'})])
print(G.edges(data=True))
G[1][2]['weight'] = 100000 #通过G[][][]来添加或修改属性
print(G.edges(data=True))
注意:
注意什么时候使用‘=’,什么时候使用‘:’;什么时候有引号什么时候没有引号。
特殊属性weight应该是一个数值型的,并且在算法需要使用weight时保存该数值。