python库整理:networkx 包
1 創建圖形
創建一個沒有節點和邊的空圖形。
import networkx as nx G = nx.Graph()根據定義,Graph是一組節點(頂點)和已識別的節點對(稱為邊、鏈接等)的集合。
1.1 清空圖
G.clear()1.2 從dataframe中導入圖信息
import numpy as np import pandas as pd import networkx as nx import matplotlib.pyplot as pltedges=pd.DataFrame() edges['sources']=[1,1,1,2,2,3,3,4,4,5,5,5] #有向邊的起點edges['targets']=[2,4,5,3,1,2,5,1,5,1,3,4] #有向邊的終點edges['weights']=[1,1,1,1,1,1,1,2,1,1,1,1] #各邊的權重G=nx.from_pandas_edgelist(edges,source='sources',target='targets',edge_attr='weights')nx.draw(G, with_labels=True) plt.show()2 節點
2.1?一次添加一個節點
G.add_node(1)2.2?從任何?iterable?容器(如列表)中添加節點
G.add_nodes_from([2, 3])2.3 從元組中添加節點和節點屬性
G.add_nodes_from([(4, {"color": "red"}),(5, {"color": "green"}), ])2.4 合并圖中一個節點到另一個圖中
H = nx.Graph() H.add_nodes_from(G)2.5 查看點的數量
G.number_of_nodes()2.6 刪除點
G.remove_node(2)G.remove_nodes_from({1,2])?2.7 設置新屬性
nx.set_node_attributes(G,value, key):將G圖每個節點的key屬性設置為value
import networkx as nx G = nx.Graph()G.add_nodes_from([(4, {"color": "red"}),(5, {"color": "green"}), ]) nx.set_node_attributes(G, -1.0, "val")G.nodes.data() #NodeDataView({4: {'color': 'red', 'val': -1.0}, 5: {'color': 'green', 'val': -1.0}})2.8 查看圖的某一個屬性
G.nodes.data() #NodeDataView({4: {'color': 'red', 'val': -1.0}, 5: {'color': 'green', 'val': -1.0}})G.nodes(data="val") #NodeDataView({4: -1.0, 5: -1.0}, data='val')for (node, obs) in G.nodes(data="val"):print(node,obs) ''' 4 -1.0 5 -1.0 '''3 邊
3.1 一次添加一條邊
G.add_edge(1, 2)#或者: e = (2, 3) G.add_edge(*e) # unpack edge tuple*3.2?添加邊列表
G.add_edges_from([(1, 2), (1, 3)])3.3? 從元組中添加邊和邊屬性
G.add_edges_from([(2, 3, {'weight': 3.1415})])3.4 查看邊的數量
G.number_of_edges()3.5 刪除邊
G.remove_edge(1, 3)G.remove_edges_from([(1, 2), (1, 3)])3.6 增加帶權邊
G.add_weighted_edges_from([(1, 2, 0.125), (1, 3, 0.75), (2, 4, 1.2), (3, 4, 0.375)])4 圖的基本屬性
一部分屬性的具體介紹可以看GNN 筆記1 圖的概念_劉文巾的博客-CSDN博客
4.1 節點集合
G = nx.Graph() G.add_node(1) G.add_nodes_from([2, 3]) G.add_edge(1, 2) G.add_edges_from([(1, 3)])print(list(G.nodes())) #[1, 2, 3]4.2 邊集合
G = nx.Graph() G.add_node(1) G.add_nodes_from([2,3]) G.add_edge(1, 2) G.add_edges_from([(1, 3, {'weight': 3.1415})])print(G.edges) #[(1, 2), (1, 3)]print(G.edges.data()) #[(1, 2, {}), (1, 3, {'weight': 3.1415})]print(G.edges.data('weight')) #[(1, 2, None), (1, 3, 3.1415)]4.2.1 可以用G[i][j]表示連接i和j的邊的信息
G = nx.Graph() G.add_node(1) G.add_nodes_from([2,3]) G.add_edge(1, 2) G.add_edges_from([(1, 3, {'weight': 3.1415})])print(G[1][2],G[1][3],G[1][3]['weight']) #{} {'weight': 3.1415} 3.14154.2.2 也可以用G.edges[i,j]表示連接i和j的邊的信息
G = nx.Graph() G.add_node(1) G.add_nodes_from([2,3]) G.add_edge(1, 2) G.add_edges_from([(1, 3, {'weight': 3.1415})])print(G.edges[1,3],G.edges[1,3]['weight']) #{'weight': 3.1415} 3.14154.3 點相鄰的集合
G = nx.Graph() G.add_node(1) G.add_nodes_from([2, 3]) G.add_edge(1, 2) G.add_edges_from([(1, 3)])print(list(G.adj[1])) #[2, 3]#或 print(list(G.neighbors(1))) #[2, 3]#或 print(G[1]) #{2: {}, 3: {}} #2和3大括號里面的是相連接的邊的性質,我們這里沒有設置#或 print(G.adj) #{1: {2: {}, 3: {}}, 2: {1: {}}, 3: {1: {}}} G = nx.Graph() G.add_node(1) G.add_nodes_from([2,3]) G.add_edge(1, 2) G.add_edges_from([(1, 3, {'weight': 3.1415})])print(G[1]) #{2: {}, 3: {'weight': 3.1415}}4.4?節點的度
G = nx.Graph() G.add_node(1) G.add_nodes_from([2, 3]) G.add_edge(1, 2) G.add_edges_from([(1, 3)])print(G.degree[1]) #2print(G.degree([1,2])) #[(1, 2), (2, 1)],表示點1的度為2,點2的度為1print(nx.degree(G)) #[(1, 2), (2, 1), (3, 1)] #G圖所有點的度#如果是加權邊,也可以顯示它的加權度(這里用到了后面第七節的多重圖) MG = nx.MultiGraph() MG.add_weighted_edges_from([(1, 2, 0.5), (1, 2, 0.75), (2, 3, 0.5)]) print(MG.degree([1],weight='weight')) #[(1, 1.25)]4.5 點射出來的邊
G = nx.Graph() G.add_node(1) G.add_nodes_from([2, 3]) G.add_edge(1, 2) G.add_edges_from([(1, 3)])print(G.edges([3,2])) #[(3, 1), (2, 1)]4.6連通分量
G=nx.Graph() G.add_edges_from([(1,2),(1,4),(1,5),(2,3),(3,5),(4,5)]) list(nx.connected_components(G)) #[{1, 2, 3, 4, 5}]4.7 圖的直徑
G=nx.Graph() G.add_edges_from([(1,2),(1,4),(1,5),(2,3),(3,5),(4,5)]) nx.diameter(G) #24.8 度中心性
G=nx.Graph() G.add_edges_from([(1,2),(1,4),(1,5),(2,3),(3,5),(4,5)]) nx.degree_centrality(G)#{1: 0.75, 2: 0.5, 4: 0.5, 5: 0.75, 3: 0.5}4.9?連接中心性
G=nx.Graph() G.add_edges_from([(1,2),(1,4),(1,5),(2,3),(3,5),(4,5)]) nx.closeness_centrality(G) #{1: 0.75, 2: 0.5, 4: 0.5, 5: 0.75, 3: 0.5}4.10 特征向量中心性
G=nx.Graph() G.add_edges_from([(1,2),(1,4),(1,5),(2,3),(3,5),(4,5)]) nx.eigenvector_centrality(G) ''' {1: 0.5298988890761731,2: 0.35775191431708964,4: 0.4271316779596084,5: 0.5298988890761731,3: 0.35775191431708964} '''4.11?中介中心性
G=nx.Graph() G.add_edges_from([(1,2),(1,4),(1,5),(2,3),(3,5),(4,5)]) nx.betweenness_centrality(G) #{1: 0.25, 2: 0.08333333333333333, 4: 0.0, 5: 0.25, 3: 0.08333333333333333}?4.12 拉普拉斯矩陣
import networkx as nx G = nx.Graph() G.add_node(1) G.add_nodes_from([2, 3]) G.add_edge(1, 2) G.add_edges_from([(1, 3)])print(G.edges([3,2])) #[(3, 1), (2, 1)nx.laplacian_matrix(G) ''' <3x3 sparse matrix of type '<class 'numpy.intc'>'with 7 stored elements in Compressed Sparse Row format> '''nx.adj_matrix(G).toarray() ''' array([[0, 1, 1],[1, 0, 0],[1, 0, 0]], dtype=int32) '''5?向圖形、節點和邊添加屬性
任何屬性都可以附加到圖形、節點或邊上。
每個圖、節點和邊都可以在關聯的屬性字典中保存鍵/值屬性對(鍵必須是可哈希的)。
默認情況下,這些屬性為空,但我們可以使用?add_edge?,?add_node?或直接對屬性字典?G.graph?,?G.nodes?和?G.edges?進行操作
5.1 圖形屬性
5.1.1?創建新圖形時分配圖形屬性
G = nx.Graph(day="Friday") G.graph #{'day': 'Friday'}5.1.2 創建后修改屬性
G.graph['day'] = "Monday" G.graph #{'day': 'Monday'}5.2 節點屬性
添加節點屬性?add_node()?,?add_nodes_from()?
G.add_node(1, time='5pm') G.add_nodes_from([3], time='2pm')修改節點屬性?G.nodes
G.nodes[1]['room'] = 714 G.nodes.data() #NodeDataView({1: {'time': '5pm', 'room': 714}, 3: {'time': '2pm'}})5.3 邊緣屬性
添加/更改邊緣屬性?add_edge()?,?add_edges_from()?
G.add_edge(1, 2, weight=4.7 )G.add_edges_from([(3, 4), (4, 5)], color='red') #兩條邊color都是redG.add_edges_from([(1, 2, {'color': 'blue'}), (2, 3, {'weight': 8})])使用下標符號
G[1][2]['weight'] = 4.7 G.edges[3, 4]['weight'] = 4.26 有向圖
有向圖用Digraph進行聲明。前面無向圖的大部分操作Digraph都可以使用。
在此基礎上,Digraph還有:
6.1 出入度
DG = nx.DiGraph() DG.add_weighted_edges_from([(1, 2, 0.5), (3, 1, 0.75)]) #添加加權邊print(DG.out_degree(1, weight='weight')) #出度,如果寫了 weight='weight',那么就是計算出度的權重 #0.5print(DG.in_degree(1)) #出度,如果沒有寫 weight='weight',那么就是計算出度(射向幾個點) #16.2 指向的點和指向它的點
DG = nx.DiGraph() DG.add_weighted_edges_from([(1, 2, 0.5), (3, 1, 0.75)]) print(list(DG.successors(1))) #[2]print(list(DG.predecessors(1))) #[3]6.3 有向圖無向圖互轉
6.3.1 有向圖轉無向圖
有兩種方法:
DG = nx.DiGraph() DG.add_weighted_edges_from([(1, 2, 0.5), (3, 1, 0.75)]) DG #直接pring(DG)不會有東西打印出來。 #在命令行里面敲下這些指令,然后出來這樣的輸出: #<networkx.classes.digraph.DiGraph at 0x27a716f4a08> #說明此時是有向圖G=DG.to_undirected() G #<networkx.classes.graph.Graph at 0x27a706601c8> #此時已經是無向圖了#或者 G=nx.Graph(DG) G #<networkx.classes.graph.Graph at 0x27a71909cc8> #此時也是無向圖6.3.2 無向圖轉有向圖
和有向圖轉無向圖一樣,也有兩種方法:
DG = nx.Graph() DG.add_weighted_edges_from([(1, 2, 0.5), (3, 1, 0.75)]) DG #<networkx.classes.graph.Graph at 0x27a71b73108> #此時是無向圖G=DG.to_directed() G #<networkx.classes.digraph.DiGraph at 0x27a71af7248> #此時是有向圖G=nx.DiGraph(DG) G #<networkx.classes.digraph.DiGraph at 0x27a71892c48> #有向圖了7 多重圖
networkx也提供了多重圖的實現。在兩個點之間可能有多條邊,每條邊描述了一些屬性。
多重圖有向圖和無向圖都有,分別是MultiGraph 和MultiDiGraph
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}有一點是需要注意的,多重圖轉回單邊圖的時候,兩個點之間只會留下權重最大的一條邊
G=nx.Graph(MG) dict(G.degree(weight='weight'))''' {1: 0.75, 2: 1.25, 3: 0.5} 1<--->2 之間本來有兩條邊,現在只留下權重大的1.25 '''8 圖的操作
8.1 子圖
G = nx.Graph() G.add_weighted_edges_from([(1, 5, 0.1),(5,2,0.1), (1, 4, 0.75), (2, 3, 0.5),(4,3,1)])SG=nx.subgraph(G,[1,2,5]) #表示SG是由G的結構,[1,2,5]這幾個點組成的子圖SG.edges.data('weight') #EdgeDataView([(1, 5, 0.1), (5, 2, 0.1)])8.2 合并圖
8.2.1 union
將兩張圖和并
G1 = nx.Graph() G1.add_edges_from([(1, 5),(5,2), (1, 4), (2, 3),(4,3)]) print(G1.nodes) #[1, 5, 2, 4, 3]G2 = nx.Graph() G2.add_edges_from([(11, 13)])#,(1,2), (1, 4), (2, 5),(4,3)]) print(G2.nodes) #[11, 13]UG=nx.union(G1,G2) print(UG.nodes) #[1, 5, 2, 4, 3, 11, 13]如果這兩張圖中有相同的點,那么會報錯
G1 = nx.Graph() G1.add_edges_from([(1, 5),(5,2), (1, 4), (2, 3),(4,3)])G2 = nx.Graph() G2.add_edges_from([(1,2), (1, 4), (2, 5),(4,3)])UG=nx.union(G1,G2) ''' NetworkXError: ('The node sets of G and H are not disjoint.', 'Use appropriate rename=(Gprefix,Hprefix)or use disjoint_union(G,H).')'''8.2.2 disjoint_union
即使兩張圖中有相同的點,也不會報錯,而是把相同的點重命名成新的點
import matplotlib.pyplot as plt G1 = nx.Graph() G1.add_edges_from([(1, 5),(5,2), (1, 4), (2, 3),(4,3)]) print(G1.nodes) #[1, 5, 2, 4, 3]G2 = nx.Graph() G2.add_edges_from([(1,2), (1, 4), (2, 5),(6,3)]) print(G2.nodes) #[1, 2, 4, 5, 6, 3]UG=nx.disjoint_union(G1,G2) print(UG.nodes) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] print(UG.edges) # 對點進行了重命名8.2.3 判斷合并效果
import matplotlib.pyplot as plt G1 = nx.Graph() G1.add_edges_from([(1, 5),(5,2), (1, 4), (2, 3),(4,3)]) nx.draw_networkx(G1) plt.show()G2 = nx.Graph() G2.add_edges_from([(1,2), (1, 4), (2, 5),(4,3)]) nx.draw_networkx(G2) plt.show()UG=nx.disjoint_union(G1,G2) nx.draw_networkx(UG) plt.show()8.3 笛卡爾乘積
cartesian_product(G,?H),G的每個點和H的每個點都需要有連接。
G1 = nx.Graph() G1.add_edges_from([(1, 5),(5,2), (1, 4), (2, 3),(4,3)]) G2 = nx.Graph() G2.add_edges_from([(1,2), (1, 4), (2, 5),(4,3)])CG=nx.cartesian_product(G1,G2)nx.draw_networkx(CG) plt.show()8.4 圖的疊加
compose(G,?H) 就是G中的邊保留,H中的邊疊加到G上
此時如果H中有和G中名稱相同的點,那么在compose函數中視為是一個點。
G1 = nx.Graph() G1.add_edges_from([(1, 5),(5,2), (1, 4), (2, 3),(4,3)]) G2 = nx.Graph() G2.add_edges_from([(1,2), (1, 4), (2, 5),(6,3)]) CG=nx.compose(G1, G2)nx.draw_networkx(CG)plt.show()原來G1中的五條邊現在都在,然后G2中的(1,4),(2,5)就是原來G1中的邊,剩下的兩條邊就是新加的邊。
8.5 補圖
complement?(g)——返回g的補圖
9 特殊的圖
9.1 全連接圖
complete_graph?(n) n個點之間兩兩連接
G=nx.complete_graph(10)nx.draw_networkx(G) plt.show()9.2 二部圖
G=nx.complete_bipartite_graph(3,3) nx.draw_networkx(G) plt.show()?
9.3 杠鈴圖
barbell_graph?(M1,M2)
——M1表示杠鈴兩頭全連接圖的頂點數
——M2表示連接兩個全連接圖的路徑中的節點數
G=nx.barbell_graph(5,4) nx.draw_networkx(G) plt.show()?
?9.4 棒棒糖圖
lollipop_graph?(m,n)
——m,棒棒糖圖頭部全連接圖的頂點數
——n,連接棒棒糖圖頭的路徑的節點數
G=nx.lollipop_graph (5,4) nx.draw_networkx(G) plt.show()9.5?彼得森圖
Petersen圖一般譯為彼得森圖,是一個由10個頂點和15條邊構成的連通簡單圖。
Petersen圖的同構多種多樣,形態各異,共120多種,然而它不是平面圖,因而沒有一種使得邊與邊沒有交點。
G=nx.petersen_graph()nx.draw_networkx(G) plt.show()每次會顯示一種彼得森圖的同構形態(比如下面是連續兩次plt.show()的結果)
9.6?塔特圖
感謝評論區的大佬給出定義!
塔特圖是具有46個頂點和69條邊的3正則圖。它的色數為4,色指數為3,周長為4,直徑為8。
塔特圖是一個三次多面體圖,但是非哈密頓圖。
因此,它是塔特猜想的一個反例(即每個三正多面體都有一個哈密頓環)。
G=nx.tutte_graph()nx.draw_networkx(G) plt.show()這個圖也有很多的異構型,比如下面是連續的兩個plt.show()的結果
9.7?小迷宮
返回一個帶有循環的小迷宮
G=nx.sedgewick_maze_graph()nx.draw_networkx(G) plt.show()9.8?3-正則柏拉圖四面體
G=nx.tetrahedral_graph()nx.draw_networkx(G) plt.show()10 圖的應用
10.1 最短路徑
G = nx.Graph() G.add_weighted_edges_from([(1, 5, 0.1),(5,2,0.1), (1, 4, 0.75), (2, 3, 0.5),(4,3,1)]nx.shortest_path(G,1,3) ''' 找點1到點3的最短路徑,但此時是不考慮weight的 只考慮1到3經過的點最少 所以此時會返回[1, 4, 3] '''nx.shortest_path_length(G,1,3) ''' 返回點1到點3的最短路徑包括幾條邊 同樣此時是不考慮weight的,只考慮1到3經過的點最少 所以此時會返回2'''nx.shortest_path(G,1,3,weight='weight') ''' 此時考慮權重了 1->5->2->3的路徑長度是小于1->4->3的 所以此時會返回[1, 5, 2, 3]'''nx.shortest_path_length(G,1,3,weight='weight') ''' 此時考慮權重了 1->5->2->3的路徑長度是小于1->4->3的 所以此時會返回0.7'''dict(nx.all_pairs_shortest_path(G)) ##每一對點之間的最小路徑 ''' {1: {1: [1], 5: [1, 5], 4: [1, 4], 2: [1, 5, 2], 3: [1, 4, 3]},5: {5: [5], 1: [5, 1], 2: [5, 2], 4: [5, 1, 4], 3: [5, 2, 3]},2: {2: [2], 5: [2, 5], 3: [2, 3], 1: [2, 5, 1], 4: [2, 3, 4]},4: {4: [4], 1: [4, 1], 3: [4, 3], 5: [4, 1, 5], 2: [4, 3, 2]},3: {3: [3], 2: [3, 2], 4: [3, 4], 5: [3, 2, 5], 1: [3, 4, 1]}} '''dict(nx.all_pairs_shortest_path_length(G)) #每一對之間的最小路徑的長度 ''' {1: {1: 0, 4: 1, 5: 1, 2: 2, 3: 2},5: {5: 0, 1: 1, 2: 1, 3: 2, 4: 2},2: {2: 0, 3: 1, 5: 1, 1: 2, 4: 2},4: {4: 0, 1: 1, 3: 1, 2: 2, 5: 2},3: {3: 0, 2: 1, 4: 1, 1: 2, 5: 2}} '''11 繪圖
import matplotlib.pyplot as plt G = nx.Graph() G.add_weighted_edges_from([(1, 5, 0.1),(5,2,0.1), (1, 4, 0.75), (2, 3, 0.5),(4,3,1)])nx.draw(G, with_labels=True, font_weight='bold') #with_labels=False的話,圖中的點點中是沒有數值的 plt.show()plt.savefig("path.png") #保存圖片總結
以上是生活随笔為你收集整理的python库整理:networkx 包的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GNN 笔记1 图的概念
- 下一篇: python库整理目录