igraph Tutorial¶
In [25]:
#導入包
import igraph
from igraph import Graph,summary,plot
In [26]:
#查看安裝包的版本,Tutorial中版本為0.6的
igraph.__version__
Out[26]:
一、Creating a graph from scratch¶
In [27]:
g = Graph(1) #生成的graph是只有一個頂點的無向圖
In [28]:
g
Out[28]:
In [29]:
print g #U:無向的,1:1個頂點,0:0條邊
1) 添加頂點 add_vertices()¶
In [30]:
g.add_vertices(2) #添加兩個頂點
In [31]:
print g #輸出:目前有3個頂點
2) 添加邊 add_edges()¶
In [32]:
#igraph使用連續性的整數從0開始用於頂點的索引,用索引對來表示邊
#如下[(0,1),(1,2)]表示兩條邊,一個是第一個頂點和第二個頂點之間的邊,第二個表示第二個頂點和第三個頂點之間的邊
In [33]:
g.add_edges([(0,1),(1,2)]) #添加兩條邊
In [34]:
print g #輸出多了邊的數量及具體的邊
In [35]:
type(g.add_edges([(2,0)])) #add_edges方法返回值為NoneType,即不返回igraph對象,與0.6版本的不同,所以不能g.add_edges([2,0]).add_edges([1,2])
Out[35]:
In [37]:
g.add_vertices(3) #增加3個頂點,此時頂點最大索引是5
g.add_edges([(2,3),(3,4),(4,5),(5,3)]) #增加四條邊
In [38]:
print g #輸出共有6個頂點,7條邊
3) 刪除頂點 delete_vertices() 刪除邊 delete_edges()¶
igraph的圖和邊的ID(索引)都是連續的,和列表索引類似,如果刪除其中的邊,后面的ID會自動更新,刪除頂點亦如此。更甚者,如果刪除了邊,頂點的ID也會變¶
In [39]:
print g
In [41]:
g.delete_vertices((2,3))
In [43]:
#刪除頂點ID為2和3的,剩余頂點ID為(0,1,4,5),同時會將涉及到的邊刪去(頂點都沒有了,邊自然也無用了),剩余邊有兩條[(0,1),(4,5)]
#而后,后面的頂點ID會自動補齊,即ID變為(0,1,2,3)(4變為2,5變為3),涉及的邊也要變更,則邊為[(0,1),(2,3)]
print g
In [47]:
g.add_vertices(2)
g.add_edges([(1,5),(3,5)])
In [48]:
print g
In [52]:
g.get_eid(1,5),g.get_eid(3,5)
Out[52]:
In [53]:
g.delete_edges(2)
In [54]:
print g
In [56]:
g.get_eid(3,5)
Out[56]:
4) summary¶
summary輸出結果和str或者print出的結果類似,只是更加靈活些¶
有如下參數,具體可看官方文檔 graph, verbosity=0, width=78, edge_list_format=’auto’,max_rows=99999, print_graph_attributes=False,print_vertex_attributes=False, print_edge_attributes=False, full=False¶
In [61]:
summary(g) #默認情況下verbosity=1:只輸出head line,即只顯示一些匯總信息之類的
In [62]:
summary(g,verbosity=1)
In [67]:
summary(g, verbosity=1, print_graph_attributes=True, print_vertex_attributes=True, print_edge_attributes=True, full=True)
In [63]:
g.__str__()
Out[63]:
二、Generating graphs¶
igraph有很多生成器,主要分為兩大類:確定性的(deterministic)和隨機性的(stochastic)。前者如果每次同一個方法且參數值相同,則生成的圖相同,而后者則每次生成的圖是不同的。¶
In [75]:
#Tree:確定性的圖生成器
g_1 = Graph.Tree(127,2) #Tree :每個頂點有兩個孩子節點和一個父節點
g_2 = Graph.Tree(127,2)
In [76]:
print g_1
In [78]:
#GRG:隨機性的圖
g_3 = Graph.GRG(100,0.2) #GRG:geometric random graph
g_4 = Graph.GRG(100,0.2)
get_edgelist()¶
In [86]:
#獲取有頂點ID對組成的列表,即圖的邊的信息
#g_1.get_edgelist()
g_1.get_edgelist()[0:5]
Out[86]:
In [87]:
g_1.get_edgelist() == g_2.get_edgelist() #確定性的圖,每次生成的是一樣的
Out[87]:
In [88]:
g_3.get_edgelist() == g_4.get_edgelist() #隨機性的圖,每次生成的不一樣
Out[88]:
In [81]:
g_3 == g_4,g_1 == g_2
Out[81]:
isomorphic() 檢驗兩個Graph對象是否是同構的¶
In [89]:
g_1.isomorphic(g_2)
Out[89]:
In [90]:
g_3.isomorphic(g_4)
Out[90]:
三、Setting and retrieving attributes¶
In [91]:
#g_5是一個簡易的社交網絡圖,頂點代表人,邊代表關系
g_5 = Graph([(0,1),(0,2),(2,3),(3,4),(4,2),(2,5),(5,0),(6,3),(5,6)])
In [92]:
print g_5
vs & es:Graph對象包含兩個比較特殊的成員vs,es,分別代表Graph對象的頂點序列和邊序列VertexSeq,EdgeSeq¶
In [96]:
g_5.vs,g_5.es
Out[96]:
可以將vs,es看作是個字典對象,進行屬性設置¶
In [97]:
g_5.vs['name']=['Alice','Bob','Claire','Dennis','Esther','Frank','Geprge']
In [98]:
g_5.vs['age']=[25,31,18,47,22,23,50]
In [99]:
g_5.vs['gender']=['f','m','f','m','f','m','m']
In [100]:
g_5.es['is_formal']=[False,False,True,True,True,False,True,False,False]
In [109]:
g_5.vs.attributes() #attributes()查看有哪些屬性
Out[109]:
In [108]:
g_5.vs.get_attribute_values('age') #get_attribute_values(key)查看屬性有哪些值
Out[108]:
In [101]:
print g_5
也可以將vs,es看作是列表對象,通過索引查看單個邊或頂點對象¶
In [110]:
g_5.vs[0]
Out[110]:
In [112]:
g_5.vs[0].attributes()
Out[112]:
In [114]:
g_5.es[2]
Out[114]:
In [115]:
g_5.es[2].attributes()
Out[115]:
In [126]:
g_5.es[2]['is_formal']=False #對單個邊或頂點對象可通過字典形式修改屬性值
In [127]:
g_5.es[2].attributes()
Out[127]:
Vertex,Edge對象一些常見的屬性¶
In [144]:
#Edge
g_5.es[2]
Out[144]:
In [139]:
g_5.es[2].source #邊的源頂點
Out[139]:
In [140]:
g_5.es[2].target #邊的目標頂點
Out[140]:
In [141]:
g_5.es[2].tuple #返回邊的源和目標頂點,以元組形式呈現
Out[141]:
In [143]:
g_5.es[2].attributes() #以字典形式返回該Vertex對象的屬性
Out[143]:
In [148]:
g_5.es[2].index #返回邊的ID
Out[148]:
In [145]:
#Vertex 沒有tuple,source,target屬性
g_5.vs[1]
Out[145]:
In [146]:
g_5.vs[1].attributes()
Out[146]:
In [147]:
g_5.vs[1].index #返回頂點對象的ID
Out[147]:
In [149]:
#修改屬性
g_5.vs[3]['foo'] = 'bar'
In [150]:
g_5.vs['foo']
Out[150]:
In [151]:
del g_5.vs['foo'] #可以使用del對屬性進行刪除
In [152]:
g_5.vs['foo']
四、Structural properties of graphs¶
如下表格總結參考 http://blog.csdn.net/u010289316/article/details/51645064¶
指標名稱 | 概念 | 比較 | 實際應用 | 對應iGraph中的方法 |
---|---|---|---|---|
點度中心度 | 在某個點上,有多少條線 | 強調某點單獨的價值 | ★作為基本點的描述 | Graph.degree() |
接近中心度 | 該點與網絡中其他點距離之和的倒數,越大說明越在中心,越能夠很快到達其他點 | 強調點在網絡的價值,越大,越在中心 | ★★基本描述,用戶價值 | Graph.closeness() |
中間中心度 | 代表最短距離是否都經過該點,如果都經過說明這個點很重要,其中包括線的中心度 | 強調點在其他點之間調節能力,控制能力指數,中介調節效應 | ★★推薦算法,用戶的控制力 | Graph.betweenness() |
特征向量中心度 | 根據相鄰點的重要性來衡量該點的價值。首先計算鄰接矩陣,然后計算鄰接矩陣的特征向量。 | 強調點在網絡的價值,並且比接近中心度厲害的是,點價值是根據近鄰點來決定的 | ★★★推薦算法,用戶潛在價值 | Graph.evcent() |
1) Graph.degree() 返回圖的度(點度中心度)¶
In [158]:
g_5.vs.__str__()
Out[158]:
In [163]:
g_5.get_edgelist()
Out[163]:
In [176]:
#degree:求頂點的度,即有多少個邊包含該頂點,參數中傳入一個列表,可以返回指定頂點的度
g_5.degree(), g_5.degree([0,2,4])
Out[176]:
In [177]:
#入度和出度
g_5.degree(mode='in'), g_5.degree(mode='out')
Out[177]:
In [178]:
g_5.indegree(),g_5.outdegree()
Out[178]:
2) Graph.closeness() 返回圖對象的接近中心度¶
In [183]:
g_5.closeness()
Out[183]:
3) Graph.edge_betweenness() 返回邊的中間中心度、Graph.betweenness() 返回頂點的中間中心度¶
In [185]:
g_5.edge_betweenness()
Out[185]:
In [186]:
g_5.get_edgelist()
Out[186]:
In [187]:
ebs = g_5.edge_betweenness()
max_eb = max(ebs)
In [188]:
max_eb
Out[188]:
In [191]:
# 返回中心度最大的邊
[g.es[idx].tuple for idx,eb in enumerate(ebs) if eb==max_eb]
Out[191]:
In [190]:
g_5.betweenness()
Out[190]:
4) Graph.evcent():點的特征向量中心度¶
In [194]:
g_5.evcent()
Out[194]:
In [195]:
plot(g_5)
Out[195]:
五、Querying vertices and edges based on attributes¶
In [198]:
g_5.degree(), g_5.maxdegree()
Out[198]:
In [199]:
g_5.vs.select(_degree = g_5.maxdegree())['name']
Out[199]:
In [202]:
g_5.vs.select(_degree = g_5.maxdegree())
Out[202]:
select(self, *args, **kwds) 可以傳位置參數和關鍵字參數¶
1)參數為位置參數¶
In [203]:
#若第一個位置參數為None,返回一個空的序列
seq = g.vs.select(None)
In [204]:
len(seq)
Out[204]:
In [207]:
#若第一個位置參數為可調用對象(函數,方法,或者類似函數可調用的對象),若返回結果為True,則包含在返回序列中
graph = Graph.Full(10)
In [208]:
print graph
In [209]:
only_odd_vertices = graph.vs.select(lambda vertex: vertex.index % 2 ==1)
In [210]:
len(only_odd_vertices)
Out[210]:
In [222]:
#若參數是可迭代的對象(列表,生成器,其他可迭代對象等),該對象必須返回整數序列,vertex的ID與返回的整數序列如有匹配上的,則包含在返回的序列中
seq = graph.vs.select([2,3,7])
In [223]:
len(seq)
Out[223]:
In [224]:
[v.index for v in seq]
Out[224]:
In [232]:
seq = seq.select([0,2]) #調用select的對象可以不必是Graph對象的完整的VexSeq
In [226]:
[v.index for v in seq]
Out[226]:
In [233]:
seq = graph.vs.select([2,3,7,'foo',4.5]) #只能是范圍內的整數,字符串,浮點數會跳過,超過范圍的整數,則報錯
In [234]:
len(seq)
Out[234]:
In [240]:
#若第一個位置參數為整數,則后面的參數也必須為整數,相當於傳了一個整數類型的list
seq = graph.vs.select(2,3,7)
In [241]:
len(seq)
Out[241]:
2) 關鍵字參數¶
用來過濾屬性或者圖的結構性質,關鍵字包含兩部分,一部分是屬性或者結構性質的名字,另一部分過濾的操作符,后者可省略,此時默認為等於。因Python語法限制,參數中出現的操作符只能有=,不能出現>,<,in等。如下是可能的關鍵字:¶
Keyword argument | Meaning |
---|---|
name_eq | 屬性/性質的值必須 等於 關鍵字參數的值 |
name_ne | ......不等於...... |
name_lt | ......小於...... |
name_le | ......小於等於...... |
name_gt | ......大於...... |
name_ge | ......大於等於...... |
name_in | ......包含......,此時參數必須是一個序列 |
name_notin | ......不包含......,此時參數必須是一個序列 |
In [243]:
print g_5
In [244]:
g_5.vs['age']
Out[244]:
In [250]:
seq_lt = g_5.vs.select(age_lt=29) # 過濾屬性age的值小於29的
#seq_lt = g_5.vs(age_lt=29) # 也可把select省去
[v.index for v in seq_lt]
Out[250]:
若屬性和結構性質的重名了,會出現歧義,此時如果關鍵字指的是結構性質需要在前面加_,即_name。否則會認為是屬性名字¶
In [252]:
g_5.get_edgelist()
Out[252]:
In [253]:
g_5.degree()
Out[253]:
In [256]:
seq_stru = g_5.vs(_degree_gt=2)
[v.index for v in seq_stru]
Out[256]:
In [258]:
seq_stru = g_5.vs(degree_gt=2) #沒有degree屬性,報錯
[v.index for v in seq_stru]
In [259]:
[vs.degree() for vs in g_5.vs]
Out[259]:
六、Layouts and plotting¶
1) 有很多種類的布局,如下為部分:¶
方法名 | 縮略名 | 算法描述 |
---|---|---|
layout_circle | circular | 確定性布局,將頂點放在圓上 |
layout_drl | drl | 采用Distributed Recursive Layout算法,適用於比較大的圖 |
layout_fruchterman_reingold | fr | 采用力引導布局的FR(Fruchterman-Reingold)算法 |
layout_kamada_kawai | kk | 采用力導向布局的KK(Kamada-Kawai)算法 |
layout_random | random | 圖的頂點隨機放置 |
layout_reingold_tilford | rt,tree | 大型樹拓撲結構,緊湊分層的展示數據結構 |
可通過兩種方式使用:1 將縮略名作為參數傳入layout()方法中,2 直接調用方法名¶
In [356]:
layout = g_5.layout('circular')
#layout = g_5.layout_circle()
plot(g_5,layout=layout)
Out[356]:
2) Drawing a Graph¶
In [357]:
layout = g_5.layout('kk')
plot(g_5,layout = layout)
Out[357]:
In [355]:
#為頂點加標簽,用顏色區別gender屬性,頂點標簽默認使用頂點的label屬性,頂點顏色默認使用color屬性
In [358]:
g_5.vs['label'] = g_5.vs['name']
In [359]:
color_dict = {'m':'blue','f':'pink'}
g_5.vs['color'] = [color_dict[gender] for gender in g_5.vs['gender']]
In [364]:
plot(g_5,layout=layout,bbox=(300,300),margin=20)
Out[364]:
In [367]:
# 除了利用label,color屬性來畫圖外,還可以在plot傳入關鍵字鍵值對來進行設定
color_dict = {'m':'black','f':'white'}
plot(g_5,layout=layout,vertex_color=[color_dict[gender] for gender in g_5.vs['gender']],bbox=(300,300))
Out[367]:
In [368]:
#可以將圖的樣式屬性放在字典中,並通過**dict_style形式傳入plot即可
visual_style = {}
visual_style['vertex_size'] = 20
visual_style['vertex_color'] = [color_dict[gender] for gender in g_5.vs['gender']]
visual_style['vertex_label'] = g_5.vs['name']
visual_style['edge_width'] = [1 + 2 * int(is_formal) for is_formal in g_5.es['is_formal']]
visual_style['layout'] = layout
visual_style['bbox'] = (300,300)
visual_style['margin'] = 20
plot(g_5,**visual_style)
Out[368]:
3)保存Graph¶
In [369]:
# 可以保存為文件PDF,PNG等格式
plot(g_5,'social_network.pdf',**visual_style)
Out[369]:
In [ ]: