【繪圖基本流程】
(1)匯入包並重新命名(為使用方便):networkx,matplotlib.pyplot
(2)建立網路
(3)繪製網路:nx.draw() #該方法可以講網路進行美化,詳情見draw()方法
(4)建立布局:pos=nx.spring_layout(BG) #該方法為可選,可以通過建立不同布局對圖進行布局方面的美化
(5)網狀圖的顯示,常用到兩種方式:A 儲存為圖片檔案;B在視窗中顯示,也可以再儲存為圖片形式
import import networkx as nx #匯入networkx包
import matplotlib.pyplot as plt #匯入繪圖包matplotlib(需要安裝,方法見第一篇筆記)
G =nx.random_graphs.barabasi_albert_graph(100,1) #產生一個BA無標度網路G
nx.draw(G) #繪製網路G
plt.savefig("ba.png") #輸出方式1: 將映像存為一個png格式的圖片檔案
plt.show() #輸出方式2: 在視窗中顯示這幅映像
【網狀圖的美化】
網狀圖的簡單美化工作,主要通過兩種途徑:
(1)通過具體化nx.draw()方法來美化,具體的參數用法:
- `node_size`: 指定節點的尺寸大小(預設是300,單位未知,就是上圖中那麼大的點)
- `node_color`: 指定節點的顏色 (預設是紅色,可以用字串簡單標識顏色,例如'r'為紅色,'b'為綠色等,具體可查看手冊),用“資料字典”賦值的時候必須對字典取值(.values())後再賦值
- `node_shape`: 節點的形狀(預設是圓形,用字串'o'標識,具體可查看手冊)
- `alpha`: 透明度 (預設是1.0,不透明,0為完全透明)
- `width`: 邊的寬度 (預設為1.0)
- `edge_color`: 邊的顏色(預設為黑色)
- `style`: 邊的樣式(預設為實現,可選: solid|dashed|dotted,dashdot)
- `with_labels`: 節點是否帶標籤(預設為True)
- `font_size`: 節點標籤字型大小 (預設為12)
- `font_color`: 節點標籤字型顏色(預設為黑色)
(2)通過使用不同的布局(layout)來美化,目前networkx中主要提供的布局方式有:
circular_layout:節點在一個圓環上均勻分布
random_layout:節點隨機分布
shell_layout:節點在同心圓上分布
spring_layout: 用Fruchterman-Reingold演算法排列節點(這個演算法我不瞭解,樣子類似多中心放射狀)
spectral_layout:根據圖的拉普拉斯特徵向量排列節點
程式碼範例:pos=nx.spring_layout(BG)
【統計指標】
本部分主要參考閆小勇老師的部落格(http://blog.sciencenet.cn/blog-404069-337511.html),特此鳴謝
(1)度、度分布
A 得到節點的度分布序列
import networkx as nx
G = nx.random_graphs.barabasi_albert_graph(1000,3) #產生一個n=1000,m=3的BA無標度網路
print G.degree(0) #返回某個節點的度
print G.degree() #返回所有節點的度
print nx.degree_histogram(G) #返回圖中所有節點的度分布序列(從1至最大度的出現頻次)
B 繪製度順序圖表
import matplotlib.pyplot as plt #匯入科學繪圖的matplotlib包
degree = nx.degree_histogram(G) #返回圖中所有節點的度分布序列
x = range(len(degree)) #產生x軸序列,從1到最大度
y = [z / float(sum(degree)) for z in degree] #將頻次轉換為頻率,這用到Python的一個小技巧:列表內涵
plt.loglog(x,y,color="blue",linewidth=2) #在雙對數座標軸上繪製度分布曲線
plt.show() #顯示圖表
注意:對於python 不熟悉的我,使用了如下語句來代替“y = [z / float(sum(degree)) for z in degree] ”,
y1=float(sum(degree))
for z in degree:
y=z/y1
print y
雖然列印出來的y與前個語句寫出的是一樣的,但是在執行 plt.loglog(x,y,color="blue",linewidth=2) 時卻出現了如下錯誤:
ValueError: x and y must have same first dimension
原因是:y = [z / float(sum(degree)) for z in degree] #得到的y為數組[ , , , ....]
for z in degree:
y=z/y1#得到的y僅為一個值
(2)聚類係數
nx.average_clustering(G) #平均群聚係數
nx.clustering(G) #各個節點的群聚係數
(3)直徑和平均距離
nx.diameter(G) #返回圖G的直徑(最長最短路徑的長度)
nx.average_shortest_path_length(G) #返回圖G所有節點間平均最短路徑長度
(4)匹配性
nx.degree_assortativity(G) #計算一個圖的度匹配性
(5)中心性(參考閆小勇老師部落格)
Degree centrality measures.(點度中心性)
degree_centrality(G) Compute the degree centrality for nodes.
in_degree_centrality(G) Compute the in-degree centrality for nodes.
out_degree_centrality(G) Compute the out-degree centrality for nodes.
Closeness centrality measures.(緊密中心性)
closeness_centrality(G[, v, weighted_edges]) Compute closeness centrality for nodes.
Betweenness centrality measures.(介數中心性)
betweenness_centrality(G[, normalized, ...]) Compute betweenness centrality for nodes.
edge_betweenness_centrality(G[, normalized, ...]) Compute betweenness centrality for edges.
Current-flow closeness centrality measures.(流緊密中心性)
current_flow_closeness_centrality(G[, ...]) Compute current-flow closeness centrality for nodes.
Current-Flow Betweenness
Current-flow betweenness centrality measures.(流介數中心性)
current_flow_betweenness_centrality(G[, ...]) Compute current-flow betweenness centrality for nodes.
edge_current_flow_betweenness_centrality(G) Compute current-flow betweenness centrality for edges.
Eigenvector centrality.(特徵向量中心性)
eigenvector_centrality(G[, max_iter, tol, ...]) Compute the eigenvector centrality for the graph G.
eigenvector_centrality_numpy(G) Compute the eigenvector centrality for the graph G.
Load centrality.
load_centrality(G[, v, cutoff, normalized, ...]) Compute load centrality for nodes.
edge_load(G[, nodes, cutoff]) Compute edge load.
說明:由於本人最近的研究主要採用無標度圖和二分圖,因此如下僅就這兩中網路進行一下介紹,如需其他類型的網路學習請參考:閆小勇老師的部落格(http://blog.sciencenet.cn/blog-404069-337689.html)
【無標度圖】
import networkx as nx
import matplotlib.pyplot as plt
BA= nx.random_graphs.barabasi_albert_graph(20,1) #產生n=20、m=1的BA無標度網路
pos = nx.spring_layout(BA) #定義一個布局,此處採用了spring布局方式
nx.draw(BA,pos,with_labels=False,node_size = 30) #繪製圖形
plt.show()
【二分圖】
import networkx as nx
import matplotlib.pyplot as plt
1. 產生二分圖
(1)由點和邊產生
>>> BG=nx.Graph()
>>> BG.add_edge(101,201)
>>> BG.add_edge(101,202)
>>> BG.add_edge(101,203)
>>> BG.add_edge(102,202)
>>> BG.add_edge(102,203)
>>> BG.add_edge(102,204)
>>> BG.add_edge(103,203)
>>> BG.add_edge(103,205)
>>> BG.add_edge(104,204)
>>> BG.add_edge(104,206)
(2)隨機產生
NetworkX還提供了多種二分圖演化模型的建立方法,在這裡把它們列出來供大家參考:
-- networkx.generators.classic.complete_bipartite_graph(n1, n2, create_using=None)
建立一個完全二分圖
-- networkx.generators.bipartite.bipartite_configuration_model (aseq, bseq, create_using=None, seed=None)
根據兩個度序列建立一個二分圖
-- networkx.generators.bipartite.bipartite_random_regular_graph(d, n, create_using=None, seed=None)
建立一個隨機的規則二分圖
-- networkx.generators.bipartite.bipartite_preferential_attachment_graph(aseq, p, create_using=None, seed=None)
建立一個優先串連的二分圖
-- networkx.generators.bipartite.bipartite_havel_hakimi_graph(aseq, bseq, create_using=None)
根據兩個度序列建立一個Havel-Hakimi模式的二分圖(下面兩個模型類似,我沒有接觸過這個模型,不太理解具體含義)
-- networkx.generators.bipartite.bipartite_reverse_havel_hakimi_graph(aseq, bseq, create_using=None)
-- networkx.generators.bipartite.bipartite_alternating_havel_hakimi_graph(aseq, bseq, create_using=None)
2. 繪製二分圖
(1)為節點著色
cd=nx.algorithms.bipartite.basic.color(BG)#得到節點的顏色字典:{101: 1, 102: 1, 201: 0, 202: 0, 203: 0, 204: 0},項目節點被賦予顏色值1,參與者節點的顏色值是0
nx.draw(BG,pos,with_labels=False,node_size=50,node_color=cd.values())#得到
注意:由於cd為“索引值對”的形式,所以必須進行取值後才能賦給node_color
(2)繪製圖
pos=nx.spring_layout(BG)
plt.show()
3.二分圖投影(二分圖變成單分圖)
NetworkX提供的networkx.project(B, nodes)方法可以完成這一工作。它接受兩個參數:一個是二分圖B,另一個是投向的節點集合nodes。
對於節點集合的提取可以用networkx.bipartite.basic.sets方法,它可以將一個二分圖的兩類節點提取為兩個集合(X,Y),其中X是項目節點,Y是參與者節點。
>>> nSet=nx.bipartite.basic.sets(BG)#nSet[0]:項目節點集;nSet[1]:參與者節點集
>>> actor=nx.project(BG,nSet[1])#向參與者節點投影
4.派系提取(單分圖變成二分圖)
NetworkX提供的networkx.make_clique_bipartite方法可以從圖中尋找派系,然後將一個派系作為一個項目節點並和該派系中的節點建立串連,從而構造一個二分圖。
>>> BG1=nx.make_clique_bipartite(actor)#接3中代碼
>>> print BG1.edges()#結果為:[(201, -1), (202, -2), (202, -1), (203, -2), (203, -1), (203, -3), (204, -4), (204, -2), (205, -3), (206, -4)]