NetworkX 使用(三)
%pylab inline
import networkx as nx
Populating the interactive namespace from numpy and matplotlib
G = nx.Graph()
G.add_node(1)
G.add_nodes_from([2,3])
G.add_edge(1,2)
e = (2,3)
G.add_edge(*e) # Unpacking tuple
G.add_edges_from([(1,2),(1,3)])
nx.draw(G)
print(G.number_of_nodes())
print(G.number_of_edges())
3
3
G[1]
AtlasView({2: {}, 3: {}})
G[1][2]['weight'] = 10
G[1]
AtlasView({2: {'weight': 10}, 3: {}})
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.adjacency():
for nbr,eattr in nbrs.items():
data=eattr['weight']
if data<0.5: print('(%d, %d, %.3f)' % (n,nbr,data))
(1, 2, 0.125)
(2, 1, 0.125)
(3, 4, 0.375)
(4, 3, 0.375)
print(list(FG.adjacency()))
type(FG.adjacency())
[(1, {2: {'weight': 0.125}, 3: {'weight': 0.75}}), (2, {1: {'weight': 0.125}, 4: {'weight': 1.2}}), (3, {1: {'weight': 0.75}, 4: {'weight': 0.375}}), (4, {2: {'weight': 1.2}, 3: {'weight': 0.375}})]
dict_itemiterator
# Convenient access to all edges is achieved with the edges method.
for (u,v,d) in FG.edges(data='weight'):
if d<0.5: print('(%d, %d, %.3f)'%(n,nbr,d))
(4, 3, 0.125)
(4, 3, 0.375)
添加 graphs
, nodes
, 和 edges
的属性
属性 (Attributes) 有 weights
, labels
, colors
, 或者你喜欢的如何 Python 对象均可添加到 graphs
, nodes
, 或者 edges
中.
Each graph, node, and edge can hold key/value attribute pairs in an associated attribute dictionary (the keys must be hashable). By default these are empty, but attributes can be added or changed using
add_edge
,add_node
or direct manipulation of the attribute dictionaries namedG.graph
,G.node
andG.edge
for a graphG
.
Graph 属性
在创建新图的时候分配图属性.
G = nx.Graph(day="Friday")
G.graph
{'day': 'Friday'}
或者,你可以在之后修改:
G.graph['day']='Monday'
G.graph
{'day': 'Monday'}
Node 属性
使用 add_node()
, add_nodes_from()
或者 G.node
添加节点属性.
G.add_node(1, time = '5pm')
G.node[1]
{'time': '5pm'}
G.add_nodes_from([3], time='2pm')
G.node[3]
{'time': '2pm'}
G.node[1]['room'] = 714
G.node[1]
{'time': '5pm', 'room': 714}
G.nodes(data=True)
NodeDataView({1: {'time': '5pm', 'room': 714}, 3: {'time': '2pm'}})
Note that adding a node to G.node does not add it to the graph, use G.add_node() to add new nodes.
Edge 属性
使用 add_edge()
, add_edges_from()
, subscript notation(下标注释), 或者 G.edge
添加边属性.
G.add_edge(1, 2, weight=4.7 )
G[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(data=True)
EdgeDataView([(1, 2, {'weight': 4.7, 'color': 'blue'}), (3, 4, {'color': 'red'}), (3, 2, {'weight': 8}), (4, 5, {'color': 'red'})])
转换图为邻接矩阵
你可以使用 nx.to_numpy_matrix(G)
将 G
转换为 numpy
矩阵. 如果是加权图,则矩阵的元素是权重值. 如果边不存在,其值则设置为 \(0\) 而不是 Infinity(无穷大). You have to manually modify those values to Infinity (float('inf'))
nx.to_numpy_matrix(G)
matrix([[0. , 0. , 4.7, 0. , 0. ],
[0. , 0. , 8. , 1. , 0. ],
[4.7, 8. , 0. , 0. , 0. ],
[0. , 1. , 0. , 0. , 1. ],
[0. , 0. , 0. , 1. , 0. ]])
nx.to_numpy_matrix(FG)
matrix([[0. , 0.125, 0.75 , 0. ],
[0.125, 0. , 0. , 1.2 ],
[0.75 , 0. , 0. , 0.375],
[0. , 1.2 , 0.375, 0. ]])
有向图
DiGraph
类提供了许多有向图中的额外算法,比如 DiGraph.out_edges()
, DiGraph.in_degree()
, DiGraph.predecessors()
, DiGraph.successors()
等。为了让算法可以在两类图中都可以工作,无向图中的 neighbors()
和 degree()
分别等价于有向图中的 successors()
和有向图中的 in_degree()
和 out_degree()
的和.
DG = nx.DiGraph()
DG.add_weighted_edges_from([(1, 2, 0.5), (1, 3, 1.1), (4, 1, 2.3)])
DG.out_degree(1) # 节点 1 的出度
2
DG.out_degree(1, weight='weight') # 节点 1 的所有出度的权值之和
1.6
list(DG.successors(1)) # 节点 1 的继承者
[2, 3]
list(DG.neighbors(1)) # 节点 1 的邻居(不包括指向节点 1 的节点)
[2, 3]
有向图与无向图的转换
H = DG.to_undirected()
# 或者
H = nx.Graph(DG)
多图(Multigraphs)
NetworkX 提供了一个类,它可以允许任何一对节点之间有多条边。类 MultiGraph
和类 MultiDiGraph
允许添加相同的边两次,这两条边可能附带不同的权值。对于有些应用程序这是非常有用的类,但是许多算法不能够很好的在这样的图中定义,比如最短路径算法,但是像 MultiGraph.degree
这种算法又可以很好的被定义。否则你应该为了很好的定义测量,而将图转化为标准的图。
MG = nx.MultiGraph()
MG.add_weighted_edges_from([(1, 2, 0.5), (1, 2, 0.75), (2, 3, 0.5)])
dict(MG.degree(weight='weight'))
GG = nx.Graph()
for n, nbrs in MG.adjacency():
for nbr, edict in nbrs.items():
minvalue = min([d['weight'] for d in edict.values()])
GG.add_edge(n, nbr, weight=minvalue)
nx.shortest_path(GG, 1, 3)
[1, 2, 3]
图的生成器和图的操作
除了通过节点和边生成图,也可以通过以下方法产生:
使用典型的图形操作:
subgraph(G, nbunch)
- 产生 nbunch 节点的子图union(G1,G2)
- 结合图disjoint_union(G1,G2)
- 假设所有节点都不同,然后结合图cartesian_product(G1,G2)
- 返回笛卡尔乘积图compose(G1,G2)
- 结合两个图并表示两者共同的节点complement(G)
- 图 G 的补图create_empty_copy(G)
- 返回同一类图的无边副本convert_to_undirected(G)
- 返回 G 的无向图convert_to_directed(G)
- 返回G的有向图
调用经典的小图
petersen = nx.petersen_graph()
tutte = nx.tutte_graph()
maze = nx.sedgewick_maze_graph()
tet = nx.tetrahedral_graph()
使用一些图形生成器
K_5 = nx.complete_graph(5)
K_3_5 = nx.complete_bipartite_graph(3, 5)
barbell = nx.barbell_graph(10, 10)
lollipop = nx.lollipop_graph(10, 20)
使用随机图发生器
er = nx.erdos_renyi_graph(100, 0.15)
ws = nx.watts_strogatz_graph(30, 3, 0.1)
ba = nx.barabasi_albert_graph(100, 5)
red = nx.random_lobster(100, 0.9, 0.9)
通过读取存储在文件中的一些标准图形格式,例如边表,邻接表,GML,GraphML,pickle,LEAD或者其他的一些格式:
nx.write_gml(red,"path.to.file")
mygraph=nx.read_gml("path.to.file")
分析图
图 G 的结构可以通过各种图论的函数来分析,例如:
G = nx.Graph()
G.add_edges_from([(1, 2), (1, 3)])
G.add_node("spam") # adds node "spam"
list(nx.connected_components(G))
[{1, 2, 3}, {'spam'}]
sorted(d for n, d in G.degree())
[0, 1, 1, 2]
nx.clustering(G)
{1: 0, 2: 0, 3: 0, 'spam': 0}
返回节点属性的函数是通过返回一个以节点为键的字典来实现的:
nx.degree(G)
DegreeView({1: 2, 2: 1, 3: 1, 'spam': 0})