创建一个图
创建一个没有节点和边的空图。
import networkx as nx
G = nx.Graph()
根据定义,a Graph
是节点(顶点)的集合以及确定的节点对(称为边,链接等)。在NetworkX中,节点可以是任何可哈希对象,例如文本字符串,图像,XML对象,另一个Graph,自定义节点对象等。
该图G
可以以几种方式生长。NetworkX包含许多图形生成器功能和设施,以多种格式读取和写入图形。开始虽然我们会看看简单的操作。您可以一次添加一个节点,
G.add_node(1)
添加一个节点列表,
G.add_nodes_from([2, 3])
或添加任何可迭代的节点容器。如果容器产生2元组(node,node_attribute_dict),您还可以添加节点以及节点属性。节点属性在下面进一步讨论。
H = nx.path_graph(10)
G.add_nodes_from(H)
请注意,G
现在包含H
作为节点的节点G
。相反,您可以将图形H
用作节点G
。
G.add_node(H)
该图G
现在包含H
作为节点。这种灵活性非常强大,因为它允许图形图形,文件图形,功能图形等等。值得思考如何构建应用程序,以便节点是有用的实体。当然,G
如果您愿意,您始终可以在节点信息中使用唯一标识符并具有由标识符键入的单独字典。注意:如果散列取决于其内容,则不应更改节点对象。
G
也可以通过一次添加一条边来增长
G.add_edge(1, 2)
e = (2, 3)
G.add_edge(*e) # unpack edge tuple*
通过添加边列表
G.add_edges_from([(1, 2), (1, 3)])
或者通过添加任何的边。一个ebunch是边元组的任何可迭代容器。边元组可以是节点的2元组,也可以是具有2个节点的3元组,后面是边属性字典,例如 。边缘属性将在下面进一步讨论(2, 3, {'weight': 3.1415})
G.add_edges_from(H.edges)
或者也可以删除图中所有节点和变
G.clear()
我们添加新的节点/边,并且NetworkX会自动的忽略任何已经存在的节点。 G.add_edges_from([(1, 2), (1, 3)])
G.add_node(1)
G.add_edge(1, 2)
G.add_node("spam") # adds node "spam"
G.add_nodes_from("spam") # adds 4 nodes: 's', 'p', 'a', 'm'
G.add_edge(3, 'm')
在这个阶段,图形G
由8个节点和3个边组成,如下所示:
>>> G.number_of_nodes()
8
>>> G.number_of_edges()
3
我们可以检查节点和边。四个基本图形属性:G.nodes
,G.edges
,G.adj
和G.degree
。这些是节点,边,邻居(邻接点)和图中节点的程度集的视图。它们为图结构提供了一个不断更新的只读视图。他们用字典通过展现你可以看一下节点和边缘数据属性和使用迭代方法与数据属性.items()
,.data('span')
。如果你想要一个特定的容器类型而不是视图,你可以指定一个。这里我们使用列表,尽管集合,字典,元组和其他容器在其他上下文中可能会更好。
>>> list(G.nodes)
['a', 1, 2, 3, 'spam', 'm', 'p', 's']
>>> list(G.edges)
[(1, 2), (1, 3), (3, 'm')]
>>> list(G.adj[1]) # or list(G.neighbors(1))
[2, 3]
>>> G.degree[1] # the number of edges incident to 1
2
可以以类似于添加的方式从图中移除节点和边。使用方法
Graph.remove_node()
,Graph.remove_nodes_from()
, Graph.remove_edge()
和 Graph.remove_edges_from()
,如
>>> G.remove_node(2)
>>> G.remove_nodes_from("spam")
>>> list(G.nodes)
[1, 3, 'spam']
>>> G.remove_edge(1, 3)
通过实例化其中一个图形类来创建图形结构时,可以使用多种格式指定数据。
>>> G.add_edge(1, 2)
>>> H = nx.DiGraph(G) # create a DiGraph using the connections from G
>>> list(H.edges())
[(1, 2), (2, 1)]
>>> edgelist = [(0, 1), (1, 2), (2, 3)]
>>> H = nx.Graph(edgelist)
可能会注意到节点和边未指定为NetworkX对象。这使您可以自由使用有意义的项目作为节点和边缘。最常见的选择是数字或字符串,但节点可以是任何可哈希对象(除外None
),并且边可以与任何x
使用的对象相关联。
G.add_edge(n1, n2, object=x)
作为一个例子,n1和
n2
可以是来自现实中的两个人,看为对象,并且x
可以参考其中一人记录,详细描述其相互关系的结果。
我们发现这种力量非常有用,但除非熟悉Python,否则它的滥用可能会导致意想不到的后果。如果有疑问,请考虑使用convert_node_labels_to_integers()
获取更具有整数标签的传统图形。
除了视图之外Graph.edges()
,Graph.adj()
还可以使用下标符号来访问边缘和邻居。
>>> G[1] # same as G.adj[1]
AtlasView({2: {}})
>>> G[1][2]
{}
>>> G.edges[1, 2]
{}
如果边缘已经存在,您可以使用下标符号来获取/设置边的属性。
>>> G.add_edge(1, 3)
>>> G[1][3]['color'] = "blue"
>>> G.edges[1, 2]['color'] = "red"
所有(节点,邻接节点)的快速查询都是使用 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)
通过边属性可以方便地访问所有的边。
>>> 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)
属性(如权重,标签,颜色或任何您喜欢的Python对象)可以附加到图形,节点或边上。
每个图形,节点和边都可以在关联的属性字典中保存键/值属性对(键必须是可散列的)。默认情况下,这些都是空的,但属性可以使用添加或更改add_edge
,add_node
或命名的属性字典的直接操作G.graph
,G.nodes
和 G.edges
一个图G
。
创建新图形时分配图形属性
>>> G = nx.Graph(day="Friday")
>>> G.graph
{'day': 'Friday'}
或者也可以修改属性
>>> G.graph['day'] = "Monday"
>>> G.graph
{'day': 'Monday'}
添加节点属性使用add_node()
,add_nodes_from()
或G.nodes
>>> G.add_node(1, time='5pm')
>>> G.add_nodes_from([3], time='2pm')
>>> G.nodes[1]
{'time': '5pm'}
>>> G.nodes[1]['room'] = 714
>>> G.nodes.data()
NodeDataView({1: {'room': 714, 'time': '5pm'}, 3: {'time': '2pm'}})
请注意,添加节点 G.nodes
不会将其添加到图形中,用于 G.add_node()
添加新节点。类似的边缘。
add_edge()
, add_edges_from()
或标符号。
>>> 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
特殊属性weight
应该是数字的,因为它需要加权边缘的算法使用。
本DiGraph
类提供专用于向边,例如额外的属性
DiGraph.out_edges()
,DiGraph.in_degree()
,DiGraph.predecessors()
,DiGraph.successors()
等。为了让算法与这两类工作轻松,的导演版本neighbors()
就相当于successors()
同时degree
报告的总和in_degree
以及out_degree
即使是可能常常不一致。
>>> DG = nx.DiGraph()
>>> DG.add_weighted_edges_from([(1, 2, 0.5), (3, 1, 0.75)])
>>> DG.out_degree(1, weight='weight')
0.5
>>> DG.degree(1, weight='weight')
1.25
>>> list(DG.successors(1))
[2]
>>> list(DG.neighbors(1))
[2]
一些算法仅适用于有向图,而其他算法不适用于有向图。事实上,将定向和无向图合并在一起的趋势是危险的。如果你想把一个有向图作为无向的进行一些测量,你应该使用Graph.to_undirected()
或者用它来转换它
>>> H = nx.Graph(G) # convert G to undirected graph
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'))
{1: 1.25, 2: 1.75, 3: 0.5}
>>> 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]
1. 应用经典图形操作,例如:
subgraph(G, nbunch) - induced subgraph view of G on nodes in nbunch
union(G1,G2) - graph union
disjoint_union(G1,G2) - graph union assuming all nodes are different
cartesian_product(G1,G2) - return Cartesian product graph
compose(G1,G2) - combine graphs identifying nodes common to both
complement(G) - graph complement
create_empty_copy(G) - return an empty copy of the same graph class
convert_to_undirected(G) - return an undirected representation of G
convert_to_directed(G) - return a directed representation of G
2. 使用其中一个经典小图的调用,例如,
>>> petersen = nx.petersen_graph()
>>> tutte = nx.tutte_graph()
>>> maze = nx.sedgewick_maze_graph()
>>> tet = nx.tetrahedral_graph()
3. 使用一个(建设性的)发电机的经典图形,例如,
4. 使用随机图生成器,例如>>> 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)
5. 使用常见图形格式(如边缘列表,邻接列表,GML,GraphML,pickle,LEDA等)读取存储在文件中的图形。>>> 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)
>>> 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)) [set([1, 2, 3]), set(['spam'])] >>> sorted(d for n, d in G.degree()) [0, 1, 1, 2] >>> nx.clustering(G) {1: 0, 2: 0, 3: 0, 'spam': 0}
一些具有大输出的函数迭代(节点,值)2元组。
dict ,
如果您愿意,这些很容易存储在结构中。>>> sp = dict(nx.all_pairs_shortest_path(G)) >>> sp[3] {1: [3, 1], 2: [3, 1, 2], 3: [3]}
绘图
NetworkX主要不是图形绘制软件包,而是包含Matplotlib的基本绘图以及使用开源Graphviz软件包的界面。这些是
networkx.drawing
模块的一部分,如果可能的话,将被导入。首先导入Matplotlib的plot界面(pylab也可以)
可能会发现使用交互式测试代码很有用,它结合了ipython和matplotlib的强大功能,并提供了一个便利的交互模式。>>> import matplotlib.pyplot as plt
ipython -pylab
G = nx.petersen_graph() plt.subplot(121) nx.draw(G, with_labels=True, font_weight='bold') plt.subplot(122) nx.draw_shell(G, nlist=[range(5, 10), range(5)], with_labels=True, font_weight='bold')
![]()
当绘制到交互式显示。请注意,您可能需要发布Matplotlib
plt.show()
命令,如果你没有在交互模式下使用matplotlib
>>> options = { ... 'node_color': 'black', ... 'node_size': 100, ... 'width': 3, ... } >>> plt.subplot(221)
>>> nx.draw_random(G, **options) >>> plt.subplot(222) >>> nx.draw_circular(G, **options) >>> plt.subplot(223) >>> nx.draw_spectral(G, **options) >>> plt.subplot(224) >>> nx.draw_shell(G, nlist=[range(5,10), range(5)], **options) 可以通过
draw_networkx()
和布局来找到其他选项layout
。你可以使用多个shelldraw_shell()
。>>> G = nx.dodecahedral_graph() >>> 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)
例如,要将绘图保存到文件中,请使用
>>> nx.draw(G) >>> plt.savefig("path.png")
写入
path.png
本地目录中的文件。如果Graphviz和PyGraphviz或pydot在您的系统上可用,您还可以使用nx_agraph.graphviz_layout(G)
或nx_pydot.graphviz_layout(G)
获取节点位置,或以点格式编写图形以供进一步处理。>>> from networkx.drawing.nx_pydot import write_dot >>> pos = nx.nx_agraph.graphviz_layout(G) >>> nx.draw(G, pos=pos) >>> write_dot(G, 'file.dot')