一、图的种类
Graph:指无向图(undirected Graph),边无向
DiGraph:指有向图(directed Graph),边有向
MultiGraph:指多重无向图,允许两节点间的边多于一条
MultiDiGraph:指多重有向图
二、创建图
1)创建图
import networkx as nx
'''
nx.Graph()
nx.DiGraph()
nx.MultiGraph()
nx.MultiDiGraph()
'''
G = nx.Graph()
G.add_edge(1,2)
#根据无向图G创建有向图H(双向)
H = nx.DiGraph(G)
#创建有向图(单向)
edgelist = [(0, 1), (1, 2), (2, 3)]
H = nx.DiGraph(edgelist)
FG = nx.Graph()
#添加带权重的边,边的key为'weight'
FG.add_weighted_edges_from([(1, 2, 0.125), (1, 3, 0.75), (2, 4, 1.2), (3, 4, 0.375)])
print(FG.adj)
2)添加节点
#添加单个节点
G.add_node(1)
#从可迭代对象添加多个节点
G.add_nodes_from([2,'tom'])
# 添加带属性的节点
G.add_nodes_from([
(4, {"color": "red"}),
(5, {"color": "green"}),
])
# 返回由10个节点挨个连接的无向图
H = nx.path_graph(10)
# 添加图H的所有节点
G.add_nodes_from(H)
3)添加边
#创建边时,没节点会先创建节点
#添加一条边
G.add_edge(1, 2)
#添加一条边
e = (2, 3)
G.add_edge(*e)
#添加多条边
G.add_edges_from([(3, 4), (4, 5)])
# 添加图H的所有边
G.add_edges_from(H.edges)
三、查看图
#图G的节点数量
print(G.number_of_nodes())
#图G的边的数量
print(G.number_of_edges())
#查看整个图
print(G.adj)
#图G的所有节点
print(list(G.nodes))
#图G的所有边
print(list(G.edges))
#节点1的相邻节点
# list(G.neighbors(1))
# G[1]
print(G.adj[1])
#节点1的边的数量
print(G.degree[1])
#节点2、3的所有边
# G[2][3]
print(G.edges([2, 3]))
#节点2、3的边的数量
print(G.degree([2, 3]))
四、删除图
#删除节点2
G.remove_node(2)
#删除节点3、4
G.remove_nodes_from([3,4])
#删除5,6之间的边
G.remove_edge(5, 6)
#清除所有节点、边
G.clear()
五、添加/修改属性
#图属性
G = nx.Graph(day="Friday")
print(G.graph)
G.graph['day'] = "Monday"
#节点属性
G.add_node(1, time='1pm')
#2、3的time相同
G.add_nodes_from([2,3], time='2pm')
#4、5的time不同
G.add_nodes_from([(4,{'time':'4pm'}),(5,{'time':'5pm'})])
G.nodes[1]['room'] = 714
print(G.nodes[4])
print(G.nodes[5])
print(G.nodes.data())
#边属性
G = nx.Graph([(1, 2, {"color": "yellow"})])
#单个边
G.add_edge(1, 2, weight=4.7 )
#边的属性都一致
G.add_edges_from([(3, 4), (4, 5)], color='red')
# 边的属性不一致
G.add_edges_from([(1, 2, {'color': 'blue'}), (2, 3, {'weight': 8})])
#增加/修改边的属性
G[1][2]['weight'] = 4.7
G.edges[3, 4]['weight'] = 4.2
print(G.edges.data())
print(G.adj)
六、图操作
# 返回由10个节点挨个连接的无向图
F = nx.path_graph(10)
G = nx.Graph()
G.add_edges_from([(1, 2),(2,3),(3,4)] )
#得到G的1,2,3的节点的子图
J = G.subgraph([1,2,3])
G = nx.Graph([('a', 'b'),('b','c'),('c','d')])
H = nx.Graph([('b','c'),('c','d'),('d','e')])
#G,H合并在一起,相同节点融合
F = nx.compose(G,H)
G = nx.Graph([(1, 2),(2,3),(3,4)])
#返回G的图补
F = nx.complement(G)
#返回G的副本,并删除所有边。
F = nx.create_empty_copy(G)
#返回G的无向图
F = nx.to_undirected(G)
#返回G的有向图
F = nx.to_directed(G)
#返回彼得森图
F = nx.petersen_graph()
#返回图特图
F = nx.tutte_graph()
#返回一个带有循环的小迷宫
F = nx.sedgewick_maze_graph()
#返回3-正则柏拉图四面体图
F = nx.tetrahedral_graph()
七、图读写
1)邻接表
读写网络图作为邻接列表。
邻接列表格式对于没有与节点或边关联的数据的图以及可以有意义地表示为字符串的节点很有用。
'''
函数参数说明:
comments='#' #注释符
delimiter=' ' #分隔符
create_using=nx.DiGraph #图类型
nodetype=str #节点类型
edgetype=None #边类型
encoding='utf-8' #字符编码
data ( bool或(label,type)元组列表 )
写入:
G.add_edge(1, 2, weight=7, color="red")
data=["color", "weight"] --> "1 2 red 7"
读取/解析:
True or False 表示是否显示属性
"1 2 red 7" --> data=(('color',str),("weight", float)) 表示边(1,2)的color属性为red,weight属性为7.0
'''
G = nx.path_graph(4)
#图写入
nx.write_adjlist(G, "test.adjlist",encoding='utf-8')
#图读取
#fh = open("test.adjlist", "rb")
#G = nx.read_adjlist(fh)
'''
#尝试将所有节点转换为整数类型
G = nx.read_adjlist("test.adjlist", nodetype=int)
#读取为有向图,默认值为 nx.Graph 无向图
G = nx.read_adjlist("test.adjlist", create_using=nx.DiGraph)
'''
G = nx.read_adjlist("test.adjlist")
#以.gz或.bz2结尾的文件名将被压缩
nx.write_adjlist(G, "test.adjlist.gz")
#图读取
G = nx.read_adjlist("test.adjlist.gz")
#图解析
lines = ["1 2 5", "2 3 4", "3 5", "4", "5"]
G = nx.parse_adjlist(lines, nodetype=int,create_using=nx.DiGraph)
#返回棒棒糖图,糖部分4个,棒部分3个
G = nx.lollipop_graph(4, 3)
# 以邻接列表格式生成图G的单行
for line in nx.generate_adjlist(G,delimiter=' '):
print(line)
2)多行邻接表
将networkx图作为多行邻接列表读写。
多行邻接列表格式对于节点可以有意义地表示为字符串的图形很有用。使用这种格式,可以存储简单的边缘数据,但节点或图形数据不能。
# 从路径读取多行邻接列表格式的图形
G = nx.Graph([('a','b'),('b','c'),('c','d'),('a','c')])
nx.write_multiline_adjlist(G, "test.adjlist")
G = nx.read_multiline_adjlist("test.adjlist")
#图解析,第一行"1 2"表示1的边有两个(后面的不记重复的边)
lines = [
"1 2",
"2 {'weight':3, 'name': 'Frodo'}",
"3 {}",
"2 1",
"5 {'weight':6, 'name': 'Saruman'}",
]
G = nx.parse_multiline_adjlist(iter(lines), nodetype=int)
# 以多行adjlist格式生成
G = nx.lollipop_graph(4, 3)
for line in nx.generate_multiline_adjlist(G):
print(line)
3)边列表
读写网络图作为边缘列表。
多行邻接列表格式对于节点可以有意义地表示为字符串的图形很有用。使用EdgeList格式,可以存储简单的边缘数据,但节点或图形数据不能。除非节点具有自循环边,否则无法表示独立节点。
#写入
G = nx.Graph()
G.add_edge(1, 2, weight=7, color="red")
# nx.write_edgelist(G, "test.edgelist", data=False)
# nx.write_edgelist(G, "test.edgelist", data=["color"])
nx.write_edgelist(G, "test.edgelist", data=["color", "weight"])
#读取
G = nx.read_edgelist("test.edgelist", nodetype=int, data=(('color',str),("weight", float)))
print(list(G.edges(data=True)))
#写入带权重的边,数据三列,第一二列表示边,第三列表示权重例如:1 2 0.5
G = nx.Graph()
G.add_edge(1, 2, weight=0.5)
nx.write_weighted_edgelist(G, "test.weighted.edgelist")
#读取带权重的边,数据三列,第一二列表示边,第三列表示权重例如:1 2 0.5
G = nx.read_weighted_edgelist("test.weighted.edgelist")
print(list(G.edges(data=True)))
#边解析
lines = ["1 2", "2 3", "3 4"]
G = nx.parse_edgelist(lines, nodetype=int)
lines = ["1 2 {'weight': 3}", "2 3 {'weight': 27}", "3 4 {'weight': 3.0}"]
G = nx.parse_edgelist(lines, nodetype=int)
lines = ["1 2 3", "2 3 27", "3 4 3.0"]
G = nx.parse_edgelist(lines, nodetype=int, data=(("weight", float),))
4)GEXF
GEXF(图形交换XML格式)是一种描述复杂网络结构及其相关数据和动态的语言。
此实现不支持混合图(有向和无向边在一起)。
'''
prettyprint ( bool(可选,默认值:true) )--如果为真,则在输出XML中使用换行符和缩进。
'''
G = nx.Graph()
G.add_nodes_from([
(4, {"color": "red"}),
(5, {"color": "green"}),
])
G.add_edge(4,5,name='tom')
#写入
nx.write_gexf(G, "test.gexf", encoding='utf-8', prettyprint=True, version='1.2draft')
#读取
G = nx.read_gexf("test.gexf", node_type=None, relabel=False, version='1.2draft')
print(G.nodes.data())
print(G.adj)
#生成G的GEXF格式表示行
G = nx.path_graph(4)
'''
s = '\n'.join(nx.generate_gexf(G))
print(s)
'''
for line in nx.generate_gexf(G):
print(line)
5)GML
GML,图形建模语言,是我们提出的一种可移植的图形文件格式。GML的主要特点是可移植性、简单的语法、可扩展性和灵活性。GML文件由层次键值列表组成。图形可以用任意数据结构进行注释。通用文件格式的想法诞生于1995年的gd;这个提议是许多讨论的结果。gml是graphlet图形编辑器系统中的标准文件格式。它已经被其他几种绘制图形的系统所取代和改编。
G = nx.DiGraph()
G.add_nodes_from([
(4, {"color": "red"}),
(5, {"color": "green"}),
])
G.add_edge(4,5,name='tom')
#写入
nx.write_gml(G, "test.gml")
#读取
G = nx.read_gml("test.gml")
print(G.nodes.data())
print(G.adj)
#生成G的GML格式表示行
G = nx.path_graph(4)
'''
s = '\n'.join(nx.generate_gml(G))
print(s)
'''
for line in nx.generate_gml(G):
print(line)
6)pickle
以python pickles的形式读写networkx图。
pickle模块实现了对python对象结构进行序列化和反序列化的基本但功能强大的算法。pickling”是一个过程,其中一个python对象层次结构被转换成一个字节流,“unpickling”是一个逆操作,其中一个字节流被转换回一个对象层次结构。
注意,networkx图可以包含任何作为节点的可哈希python对象(不仅仅是整数和字符串)。对于任意数据类型,可能很难将数据表示为文本。在这种情况下,可以使用python pickles来存储图形数据。
G = nx.DiGraph()
G.add_nodes_from([
(4, {"color": "red"}),
(5, {"color": "green"}),
])
G.add_edge(4,5,name='tom')
#写入
nx.write_gpickle(G, "test.gpickle")
#读取
G = nx.read_gpickle("test.gpickle")
print(G.nodes.data())
print(G.adj)
7)graphml
以图形格式读取和写入图形。
此实现不支持混合图(有向和无向边在一起)、超边、嵌套图或端口。
“graphml是一种全面且易于使用的图形文件格式。它由描述图的结构属性的语言核心和添加特定于应用程序的数据的灵活扩展机制组成。它的主要功能包括支持
有向图、无向图和混合图,
超图,
层次图,
图形表示,
引用外部数据,
应用程序特定的属性数据,以及
重量轻的解析器。
与许多其他图形文件格式不同,graphml不使用自定义语法。相反,它是基于XML的,因此非常适合作为生成、存档或处理图形的所有类型服务的通用分母。”
http://graphml.graphdrawing.org/
G = nx.DiGraph()
G.add_nodes_from([
(4, {"color": "red"}),
(5, {"color": "green"}),
])
G.add_edge(4,5,name='tom')
#写入
nx.write_graphml(G, "test.graphml")
#读取
G = nx.read_graphml("test.graphml", node_type=int, edge_key_type=int)
print(G.nodes.data())
print(G.adj)
#生成G的graphml格式表示行
G = nx.path_graph(4)
'''
s = '\n'.join(nx.generate_graphml(G))
print(s)
'''
for line in nx.generate_graphml(G):
print(line)
s = '\n'.join(nx.generate_graphml(G))
#graphml字符串解析成图
H = nx.parse_graphml(s)
print(H.nodes.data())
print(H.adj)
8)JSON
from networkx.readwrite import json_graph
import json
G = nx.DiGraph(index=1)
G.add_nodes_from([
(4, {"color": "red"}),
(5, {"color": "green"}),
])
G.add_edge(4,5,name='tom')
'''
建立方式一致(有的没有attrs参数,很多会去掉G.graph信息):
node_link_data node_link_graph
adjacency_data adjacency_graph
cytoscape_data cytoscape_graph
jit_data jit_graph
建立方式稍有区别:
#以节点4为根节点
data = json_graph.tree_data(G,root=4)
#读取
G = json_graph.tree_graph(data)
print(G.nodes.data())
print(G.adj)
#去掉了图的信息
print(G.graph)
'''
#存储,更改默认的key
data = json_graph.node_link_data(G, attrs={"link": "edges", "source": "from", "target": "to"})
print(data)
with open('test.json','w',encoding='utf-8') as fp:
json.dump(data, fp, ensure_ascii=False, indent=4)
#读取
with open('test.json',encoding='utf-8') as fp:
data = json.load(fp)
G = json_graph.node_link_graph(data, attrs={"link": "edges", "source": "from", "target": "to"})
print(G.nodes.data())
print(G.adj)
print(G.graph)
9)YAML
以yaml格式读取和写入networkx图。
“yaml是一种数据序列化格式,设计用于人的可读性和与脚本语言的交互。”有关文档,请参阅http://www.yaml.org。
G = nx.DiGraph(index=1)
G.add_nodes_from([
(4, {"color": "red"}),
(5, {"color": "green"}),
])
G.add_edge(4,5,name='tom')
G.add_edge(5,6)
G.add_edge(6,7)
nx.write_yaml(G, "test.yaml")
G = nx.read_yaml("test.yaml")
print(G.nodes.data())
print(G.adj)
print(G.graph)
10)graph6和 SARSE6
graph6和 SARSE6 是以紧凑的方式存储无向图的格式,只使用可打印的ASCII字符。这些格式的文件具有文本类型,并且每个图形包含一行。
graph6 适用于小图或大密图。 SARSE6 对于大型稀疏图来说,空间效率更高。
http://users.cecs.anu.edu.au/~bdm/data/formats.html
'''
to_graph6_bytes 将简单的无向图转换为GRAPH6格式的字节。
from_graph6_bytes 从字节中读取graph6格式的简单无向图。
write_graph6 将一个简单的无向图以图6格式写入路径。
read_graph6 从路径中读取以图6格式表示的简单无向图。
to_sparse6_bytes 将无向图转换为稀疏6格式的字节。
from_sparse6_bytes 从字符串中读取Spare6格式的无向图。
write_sparse6 以sparse6格式将图形G写入给定路径。
read_sparse6 从path读取sparse6格式的无向图。
'''
G = nx.DiGraph(index=1)
G.add_nodes_from([
(4, {"color": "red"}),
(5, {"color": "green"}),
])
G.add_edge(4,5,name='tom')
G.add_edge(5,6)
G.add_edge(6,7)
#header表示是否加入graph6的头部信息
data = nx.to_graph6_bytes(G,header=False)
H = nx.from_graph6_bytes(b'Ch')
nx.write_graph6(G,'test.graph6')
H = nx.read_graph6('test.graph6')
11)Pajek
阅读Pajek格式的图表。
这个实现处理有向图和无向图,包括自循环图和平行边图。
G = nx.DiGraph(index=1)
G.add_nodes_from([
(4, {"color": "red"}),
(5, {"color": "green"}),
])
G.add_edge(4,5,name='tom')
G.add_edge(5,6)
G.add_edge(6,7)
nx.write_pajek(G, "test.net")
H = nx.read_pajek("test.net")
print(H.nodes.data())
print(H.adj)
print(H.graph)
data = nx.generate_pajek(G)
for i in data:
print(i)
八、绘图
import matplotlib.pyplot as plt
G = nx.DiGraph(index=1)
G.add_nodes_from([
(4, {"color": "red"}),
(5, {"color": "green"}),
])
G.add_edge(4,5,name='tom')
G.add_edge(5,6)
G.add_edge(6,7)
#with_labels是否带节点名称
nx.draw(G, with_labels=True)
plt.show()
九、经典算法
nx.dijkstra_path(G, source, target, weight='weight') ————求最短路径
nx.dijkstra_path_length(G, source, target, weight='weight') ————求最短距离