NetworkX使用手冊
介紹
NetworkX是一款Python的軟件包,用于創(chuàng)造、操作復雜網(wǎng)絡,以及學習復雜網(wǎng)絡的結構、動力學及其功能。?有了NetworkX你就可以用標準或者不標準的數(shù)據(jù)格式加載或者存儲網(wǎng)絡,它可以產(chǎn)生許多種類的隨機網(wǎng)絡或經(jīng)典網(wǎng)絡,也可以分析網(wǎng)絡結構,建立網(wǎng)絡模型,設計新的網(wǎng)絡算法,繪制網(wǎng)絡等等。?如果在此之前你還不太了解Python,戳這里——>
安裝
其實如果要用NetworkX來進行復雜網(wǎng)絡的編程還離不開許多相關的其他Python庫,我們可以去官網(wǎng)根據(jù)需求一一安裝,有詳細的安裝說明。這里推薦一種超級方便實用的方法,即安裝Anaconda,Anaconda包含了許多實用的常用Python庫,你就不需要再一一自己安裝了。請參考。(Anaconda是跨平臺的Windows和Linux都支持)
基本使用
(下面實驗如果沒有特殊說明,都是在Ubuntu下使用Visual Studio Code實驗的)
創(chuàng)建一個圖 ?首先創(chuàng)建一個空的圖
import networkx as nx
G = nx.Graph()根據(jù)圖的定義,一個圖包含一個節(jié)點集合和一個邊集。在NetworkX中,節(jié)點可以是任何哈希對象,像一個文本字符串,一幅圖像,一個XML對象,甚至是另一個圖或任意定制的節(jié)點對象。(注意,Python中的None對象是不可以作為節(jié)點的類型的。)
節(jié)點 ?圖G可以通過好幾種方式生成。NetworkX包含了許多圖的產(chǎn)生函數(shù)和一些讀寫圖的工具。我們可以通過一些簡單的操作開始 ?最簡單的我們一次添加一個節(jié)點:
`G.add_node(1)`
也可以從一個list中添加節(jié)點:?
`G.add_nodes_from([2, 3])`
或者從**nbunch**中添加節(jié)點,nbunch是任何可迭代的節(jié)點容器(如list、set、graph、file等),nbunch本身不是圖中的一個節(jié)點。
H=nx.path_graph(10) #H是一個有10個節(jié)點的鏈狀圖,即有n個節(jié)點n-1條邊的連通圖
G.add_nodes_from(H) #或者G.add_nodes_from(H.nodes())此時圖G中就包含了圖H中的10個節(jié)點。作為比較,我們可以使圖H作為圖G的一個節(jié)點:
`G.add_node(H)`
現(xiàn)在圖G就包含了一個節(jié)點H,即該節(jié)點是一個圖。可以看到這種靈活性是非常強大的,它允許圖的圖,文件的圖,函數(shù)的圖等等。因此我們應該好好思考如何構建我們的應用程序才能使我們的節(jié)點是有用的實體。當然我們可以在圖中使用一個唯一的標識符或者使用一個不同的字典的鍵來標識節(jié)點信息。(如果該hash依賴于它的內(nèi)容,則我們不應該改變節(jié)點對象)
邊 ?一個圖G可以通過一次添加一條邊來構成:
G.add_edge(1,2)#等價于
e=(1,2) #e是一個元組
G.add_edge(*e) #這是python中解包裹的過程也可以通過添加list來添加多條邊:
G.add_edges_from([(1,2),(1,3)])或者通過添加任何ebunch來添加邊,一個ebunch是任何可迭代的邊的元組,一個邊的元組可以是兩個節(jié)點之間的一個2元組(無權值的邊)或者3元組(3元組還有一個元素是邊的權值,比如(1,2,{‘weight’:100}))。下面將進一步討論邊的屬性:
G.add_edges_from(H.edges()) #不能寫作G.add_edges_from(H)我們可以用類似的方法拆除圖:G.remove_node(),G.remove_nodes_from(),G.remove_edge(),G.remove_edges_from() ?比如:
G.remove_node(H)如果你添加的節(jié)點和邊是已經(jīng)存在的,是不會報錯的。比如,我們先將圖G里的所有節(jié)點和邊刪除:
G.clear()然后我們新的節(jié)點和邊,NetworkX會自動忽略掉已經(jīng)存在的邊和節(jié)點的添加:
G.add_edges_from([(1,2),(1,3)])
G.add_node(1)
G.add_edge(1,2)
G.add_node("spam") #添加節(jié)點"spam"
G.add_nodes_from("spam") #添加節(jié)點's' 'p' 'a' 'm'此時圖G一共有8個節(jié)點和2條邊。?我們可以通過如下函數(shù)查看:
print G.number_of_nodes()
print G.number_of_edges()此時對應的網(wǎng)絡G的圖形為:?
?我們還可以查閱當前圖G的實際情況:?
當我們通過某一種圖類創(chuàng)建一個圖形結構的實例時,我們可以指定好幾種不同格式的數(shù)據(jù): ?
?可以看到將圖G轉(zhuǎn)化為有向圖賦給H之后,有向圖H由無向圖G中的兩條無向邊轉(zhuǎn)變?yōu)?條有向邊。后面一個例子是將list直接傳到類Graph中,創(chuàng)建由list中的邊組成的無向圖H。- 節(jié)點和邊的使用 ?你可能已經(jīng)注意到在NetworkX中節(jié)點和邊并沒有被指定一個對象,因此你就可以自由地指定節(jié)點和邊的對象。最常見的對象是數(shù)值和字符串,但是一個節(jié)點可以是任意hash對象(除了None對象),一條邊也可以關聯(lián)任意的對象x,比如:G.add_edge(a,b,object=x)。?舉個關于邊關聯(lián)對象的例子,加入a和b是兩個人,而他們兩個人之間的聯(lián)系(邊),可以是一個概率,即邊的對象是一個概率值,表示這兩個人之間每天通電話的可能性。?可以看到這是十分強大而且有用的,但是如果你濫用該方法將會導致意想不到的后果,除非你對Python真的很熟悉。如果你不是很確定,你可以考慮使用conver_node_label_to_integers(),他可以將一個圖的所有節(jié)點按順序轉(zhuǎn)化為整數(shù)對象賦給另一個圖。- 訪問邊 ?除了上面的提到的那些訪問節(jié)點和邊的方法以外( eg: Graph.nodes(),Graph.edges(),Graph.neighbors()…),當你只是想想要遍歷它們時,迭代的版本(eg: Graph.edges_iter())可以省去返回它們時創(chuàng)建如此很大的一個表去存儲它們??焖僦苯拥脑L問圖的數(shù)據(jù)結構可以通過下表來實現(xiàn)。?(注意:不要去改變返回的字典,因為它是圖數(shù)據(jù)結構中的一部分,直接的操作可能導致圖處于一個不一致的狀態(tài)。) ?
?但是我們可以很安全的去改變一條已存在的邊的屬性(權值):?
如果想要快速遍歷每一條邊,我們可以使用鄰接迭代器實現(xiàn),對于無向圖,每一條邊相當于兩條有向邊:?
?(add_weight_edges_from函數(shù)的作用是通過一個ebunch添加一些節(jié)點和邊,邊默認其屬性為”weight”) ?說明:其實FG.adjacency_iter()返回的是一個所有節(jié)點的二元組(node, adjacency dict)的迭代器,比如上述代碼中對于節(jié)點1返回的是:(1,{2:{0.125},3:{0.75}})。?一種方便的訪問所有邊的方法: ?
給圖、節(jié)點和邊添加屬性 ?屬性諸如weight,labels,colors,或者任何對象,你都可以附加到圖、節(jié)點或邊上。?對于每一個圖、節(jié)點和邊都可以在關聯(lián)的屬性字典中保存一個(多個)鍵-值對。默認情況下這些是一個空的字典,但是我們可以增加或者是改變這些屬性通過使用add_edge,add_node或者字典操作這些屬性字典,比如G.graph,G.node或者G.edge。
通過讀取存儲在文件中的一些標準圖形格式,例如邊表,鄰接表,GML,GraphML,pickle,LEAD或者其他的一些格式: 使用隨機圖發(fā)生器 使用一些圖形生成器 使用典型的圖形操作:subgraph(G, nbunch) - 產(chǎn)生nbunch節(jié)點的子圖 ?union(G1,G2) - 結合圖 ?disjoint_union(G1,G2) - 假設所有節(jié)點都不同,然后結合圖 ?cartesian_product(G1,G2) - 返回笛卡爾乘積圖 ?compose(G1,G2) - 結合兩個圖并表示兩者共同的節(jié)點 ?complement(G) - 圖G的補圖 ?create_empty_copy(G) - 返回同一類圖的無邊副本 ?convert_to_undirected(G) - 返回G的無向圖 ?convert_to_directed(G) - 返回G的有向圖- 調(diào)用經(jīng)典的小圖 - 圖的屬性 ?可以在創(chuàng)建圖時分配圖的屬性:?
?你也可以修改已有的屬性:?
?你也可以隨時添加新的屬性到圖中:?
- 節(jié)點的屬性 ?通過add_node(),add_nodes_from給節(jié)點添加屬性或者G.node[][]來修改屬性(前面兩種在添加的是已存在的節(jié)點時,也可以看做是修改節(jié)點屬性 ):?
?注意添加一個節(jié)點是G.add_node而不是G.node。- 邊點的屬性 ?通過add_edge(),add_edges_from()來添加邊的屬性,下表或者G.edge[][][]來修改屬性。?
?注意:注意什么時候使用‘=’,什么時候使用‘:’;什么時候有引號什么時候沒有引號。?特殊屬性weight應該是一個數(shù)值型的,并且在算法需要使用weight時保存該數(shù)值。有向圖 ?DiGraph類提供了許多有向圖中的額外算法,比如DiGraph.out_edges(),DiGraph.in_degree(),DiGraph.predecessors(),DiGraph.successors()等。為了讓算法可以在兩類圖中都可以工作,無向圖中的neighbors()和degree()分別等價于有向圖中的successors()和有向圖中的in_degree()和out_degree()的和。雖然這樣有時候會讓我們感覺不太一致。?










有些算法只能在有向圖中使用,而有些圖并沒有為有向圖定義。確實將有向圖和無向圖混在在一起是很危險的一件事情,所以,如果有些實驗你想把一個有向圖看做一個無向圖,你可以將有向圖轉(zhuǎn)化為無向圖,通過:
H=DG.to_undirected()
#或者
H=nx.Graph(DG)
多圖(Multigraphs) ?NetworkX提供了一個類,它可以允許任何一對節(jié)點之間有多條邊。類MultiGraph和類MultiDiGraph允許添加相同的邊兩次,這兩條邊可能附帶不同的權值。對于有些應用程序這是非常有用的類,但是許多算法不能夠很好的在這樣的圖中定義,比如最短路徑算法,但是像MultiGraph.degree這種算法又可以很好的被定義。否則你應該為了很好的定義測量,而將圖轉(zhuǎn)化為標準的圖。?
圖的生成器和圖的操作 ?除了通過節(jié)點和邊生成圖,也可以通過以下方法產(chǎn)生:
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)
nx.write_gml(red,"path.to.file")
mygraph=nx.read_gml("path.to.file")
詳細的圖的格式請參考官網(wǎng):?詳細的圖的產(chǎn)生函數(shù)請參考官網(wǎng):
分析圖 ?圖G的結構可以通過各種圖論的函數(shù)來分析,例如:
>>>?G=nx.Graph()
>>>?G.add_edges_from([(1,2),(1,3)])
>>>?G.add_node("spam")???????#?adds?node?"spam"
>>>?nx.connected_components(G)
[[1,?2,?3],?['spam']]
>>>?sorted(nx.degree(G).values())
[0,?1,?1,?2]
>>>?nx.clustering(G)
{1:?0.0,?2:?0.0,?3:?0.0,?'spam':?0.0}
返回節(jié)點屬性的函數(shù)是通過返回一個以節(jié)點為鍵的字典來實現(xiàn)的:
>>>?nx.degree(G)
{1:?2,?2:?1,?3:?1,?'spam':?0}
對于一些特定節(jié)點的值,我們可以提供該特定節(jié)點(集)的nbunch作為函數(shù)參數(shù)。如果被指定的是單個節(jié)點,則返回一個對應的單一的值,如果被指定的是一個nbunch,則返回一個字典:
>>>?nx.degree(G,1)
2
>>>?G.degree(1)
2
>>>?G.degree([1,2])
{1:?2,?2:?1}
>>>?sorted(G.degree([1,2]).values())
[1,?2]
>>>?sorted(G.degree().values())
[0,?1,?1,?2]
繪制圖 ?NetworkX并不是專門用來繪圖的包,但是Matplotlib以及一些接口卻提供了很好的繪圖功能。Python3.0以上的版本可能不能很好的兼容NetworkX中的繪圖包。
首先我們導入Matplotlib的plot接口(pylab也可以)
import?matplotlib.pyplot?as?plt
#或者
import?matplotlib.pylab?as?plt
你可能會發(fā)現(xiàn)使用“ipthon -pylab”q去交互測試代碼是很有用的,它提供了強大的ipython和matplotlib,也提供了一個方便的交互模式。
測試networkx.drawing是是否導入成功,可以通過:
nx.draw(G)
nx.draw_random(G)
nx.draw_circular(G)
nx.draw_spectral(G)
你要將這個圖形繪制到屏幕,你可能需要Matplotlib:
plt.show()
如果你不需要顯示,那你可以將圖像保存到一個文件:
nx.draw(G)
plt.savefig("path.png")
最基礎的NetworkX的介紹和使用說明到這里就先結束了,后期還會繼續(xù)學習更深入的NetworkX和復雜網(wǎng)絡相結合的相關用法。


Python“寶藏級”公眾號【Python之王】專注于Python領域,會爬蟲,數(shù)分,C++,tensorflow和Pytorch等等。
近 2年共原創(chuàng) 100+ 篇技術文章。創(chuàng)作的精品文章系列有:
日常收集整理了一批不錯的?Python?學習資料,有需要的小伙可以自行免費領取。
獲取方式如下:公眾號回復資料。領取Python等系列筆記,項目,書籍,直接套上模板就可以用了。資料包含算法、python、算法小抄、力扣刷題手冊和 C++ 等學習資料!
