igraph Tutorial

 

igraph Tutorial

In [25]:
#导入包
import igraph
from igraph import Graph,summary,plot
In [26]:
#查看安装包的版本,Tutorial中版本为0.6的
igraph.__version__
Out[26]:
'0.7.1'
 

一、Creating a graph from scratch

In [27]:
g = Graph(1) #生成的graph是只有一个顶点的无向图
In [28]:
g
Out[28]:
<igraph.Graph at 0x5c58048>
In [29]:
print g #U:无向的,1:1个顶点,0:0条边
 
IGRAPH U--- 1 0 --
 

1) 添加顶点 add_vertices()

In [30]:
g.add_vertices(2) #添加两个顶点
In [31]:
print g #输出:目前有3个顶点
 
IGRAPH U--- 3 0 --
 

2) 添加边 add_edges()

In [32]:
#igraph使用连续性的整数从0开始用于顶点的索引,用索引对来表示边
#如下[(0,1),(1,2)]表示两条边,一个是第一个顶点和第二个顶点之间的边,第二个表示第二个顶点和第三个顶点之间的边
In [33]:
g.add_edges([(0,1),(1,2)]) #添加两条边
In [34]:
print g #输出多了边的数量及具体的边
 
IGRAPH U--- 3 2 --
+ edges:
0--1 1--2
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]:
NoneType
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条边
 
IGRAPH U--- 6 7 --
+ edges:
0--1 1--2 0--2 2--3 3--4 4--5 3--5
 

3) 删除顶点 delete_vertices() 删除边 delete_edges()

 

igraph的图和边的ID(索引)都是连续的,和列表索引类似,如果删除其中的边,后面的ID会自动更新,删除顶点亦如此。更甚者,如果删除了边,顶点的ID也会变

In [39]:
print g
 
IGRAPH U--- 6 7 --
+ edges:
0--1 1--2 0--2 2--3 3--4 4--5 3--5
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
 
IGRAPH U--- 4 2 --
+ edges:
0--1 2--3
In [47]:
g.add_vertices(2)
g.add_edges([(1,5),(3,5)])
In [48]:
print g
 
IGRAPH U--- 6 4 --
+ edges:
0--1 2--3 1--5 3--5
In [52]:
g.get_eid(1,5),g.get_eid(3,5)
Out[52]:
(2, 3)
In [53]:
g.delete_edges(2)
In [54]:
print g
 
IGRAPH U--- 6 3 --
+ edges:
0--1 2--3 3--5
In [56]:
g.get_eid(3,5)
Out[56]:
2
 

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,即只显示一些汇总信息之类的
 
IGRAPH U--- 6 3 -- 
In [62]:
summary(g,verbosity=1)
 
IGRAPH U--- 6 3 -- 
+ edges:
0--1 2--3 3--5
In [67]:
summary(g, verbosity=1, print_graph_attributes=True, print_vertex_attributes=True, print_edge_attributes=True, full=True)
 
IGRAPH U--- 6 3 -- 
+ edges:
0--1 2--3 3--5
In [63]:
g.__str__()
Out[63]:
'IGRAPH U--- 6 3 --\n+ edges:\n0--1 2--3 3--5'
 

二、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
 
IGRAPH U--- 127 126 --
+ edges:
0--1 0--2 1--3 1--4 2--5 2--6 3--7 3--8 4--9 4--10 5--11 5--12 6--13 6--14
7--15 7--16 8--17 8--18 9--19 9--20 10--21 10--22 11--23 11--24 12--25 12--26
13--27 13--28 14--29 14--30 15--31 15--32 16--33 16--34 17--35 17--36 18--37
18--38 19--39 19--40 20--41 20--42 21--43 21--44 22--45 22--46 23--47 23--48
24--49 24--50 25--51 25--52 26--53 26--54 27--55 27--56 28--57 28--58 29--59
29--60 30--61 30--62 31--63 31--64 32--65 32--66 33--67 33--68 34--69 34--70
35--71 35--72 36--73 36--74 37--75 37--76 38--77 38--78 39--79 39--80 40--81
40--82 41--83 41--84 42--85 42--86 43--87 43--88 44--89 44--90 45--91 45--92
46--93 46--94 47--95 47--96 48--97 48--98 49--99 49--100 50--101 50--102
51--103 51--104 52--105 52--106 53--107 53--108 54--109 54--110 55--111
55--112 56--113 56--114 57--115 57--116 58--117 58--118 59--119 59--120
60--121 60--122 61--123 61--124 62--125 62--126
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]:
[(0, 1), (0, 2), (1, 3), (1, 4), (2, 5)]
In [87]:
g_1.get_edgelist() == g_2.get_edgelist() #确定性的图,每次生成的是一样的
Out[87]:
True
In [88]:
g_3.get_edgelist() == g_4.get_edgelist() #随机性的图,每次生成的不一样
Out[88]:
False
In [81]:
g_3 == g_4,g_1 == g_2
Out[81]:
(False, False)
 

isomorphic() 检验两个Graph对象是否是同构的

In [89]:
g_1.isomorphic(g_2)
Out[89]:
True
In [90]:
g_3.isomorphic(g_4)
Out[90]:
False
 

三、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
 
IGRAPH U--- 7 9 --
+ edges:
0 -- 1 2 5     2 -- 0 3 4 5   4 -- 2 3       6 -- 3 5
1 -- 0         3 -- 2 4 6     5 -- 0 2 6
 

vs & es:Graph对象包含两个比较特殊的成员vs,es,分别代表Graph对象的顶点序列和边序列VertexSeq,EdgeSeq

In [96]:
g_5.vs,g_5.es
Out[96]:
(<igraph.VertexSeq at 0x5cad688>, <igraph.EdgeSeq at 0x5c5ceb8>)
 

可以将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]:
['gender', 'age', 'name']
In [108]:
g_5.vs.get_attribute_values('age') #get_attribute_values(key)查看属性有哪些值 
Out[108]:
[25, 31, 18, 47, 22, 23, 50]
In [101]:
print g_5
 
IGRAPH UN-- 7 9 --
+ attr: age (v), gender (v), name (v), is_formal (e)
+ edges (vertex names):
 Alice -- Bob, Claire, Frank
   Bob -- Alice
Claire -- Alice, Dennis, Esther, Frank
Dennis -- Claire, Esther, Geprge
Esther -- Claire, Dennis
 Frank -- Alice, Claire, Geprge
Geprge -- Dennis, Frank
 

也可以将vs,es看作是列表对象,通过索引查看单个边或顶点对象

In [110]:
g_5.vs[0]
Out[110]:
igraph.Vertex(<igraph.Graph object at 0x0000000005C58138>,0,{'gender': 'f', 'age': 25, 'name': 'Alice'})
In [112]:
g_5.vs[0].attributes()
Out[112]:
{'age': 25, 'gender': 'f', 'name': 'Alice'}
In [114]:
g_5.es[2]
Out[114]:
igraph.Edge(<igraph.Graph object at 0x0000000005C58138>, 2, {'is_formal': True})
In [115]:
g_5.es[2].attributes()
Out[115]:
{'is_formal': True}
In [126]:
g_5.es[2]['is_formal']=False #对单个边或顶点对象可通过字典形式修改属性值
In [127]:
g_5.es[2].attributes()
Out[127]:
{'is_formal': False}
 

Vertex,Edge对象一些常见的属性

In [144]:
#Edge
g_5.es[2]
Out[144]:
igraph.Edge(<igraph.Graph object at 0x0000000005C58138>, 2, {'is_formal': False})
In [139]:
g_5.es[2].source #边的源顶点
Out[139]:
2
In [140]:
g_5.es[2].target #边的目标顶点
Out[140]:
3
In [141]:
g_5.es[2].tuple #返回边的源和目标顶点,以元组形式呈现
Out[141]:
(2, 3)
In [143]:
g_5.es[2].attributes() #以字典形式返回该Vertex对象的属性
Out[143]:
{'is_formal': False}
In [148]:
g_5.es[2].index #返回边的ID
Out[148]:
2
In [145]:
#Vertex 没有tuple,source,target属性
g_5.vs[1]
Out[145]:
igraph.Vertex(<igraph.Graph object at 0x0000000005C58138>,1,{'gender': 'm', 'age': 31, 'name': 'Bob'})
In [146]:
g_5.vs[1].attributes()
Out[146]:
{'age': 31, 'gender': 'm', 'name': 'Bob'}
In [147]:
g_5.vs[1].index #返回顶点对象的ID
Out[147]:
1
In [149]:
#修改属性
g_5.vs[3]['foo'] = 'bar'
In [150]:
g_5.vs['foo']
Out[150]:
[None, None, None, 'bar', None, None, None]
In [151]:
del g_5.vs['foo'] #可以使用del对属性进行删除
In [152]:
g_5.vs['foo']
 
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-152-8a5b1ed9423a> in <module>()
----> 1g_5.vs['foo']

KeyError: 'Attribute does not exist'
 

四、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]:
'<igraph.VertexSeq object at 0x0000000005CC0F48>'
In [163]:
g_5.get_edgelist()
Out[163]:
[(0, 1), (0, 2), (2, 3), (3, 4), (2, 4), (2, 5), (0, 5), (3, 6), (5, 6)]
In [176]:
#degree:求顶点的度,即有多少个边包含该顶点,参数中传入一个列表,可以返回指定顶点的度
g_5.degree(), g_5.degree([0,2,4])
Out[176]:
([3, 1, 4, 3, 2, 3, 2], [3, 4, 2])
In [177]:
#入度和出度
g_5.degree(mode='in'), g_5.degree(mode='out') 
Out[177]:
([3, 1, 4, 3, 2, 3, 2], [3, 1, 4, 3, 2, 3, 2])
In [178]:
g_5.indegree(),g_5.outdegree()
Out[178]:
([3, 1, 4, 3, 2, 3, 2], [3, 1, 4, 3, 2, 3, 2])
 

2) Graph.closeness() 返回图对象的接近中心度

In [183]:
g_5.closeness()
Out[183]:
[0.6666666666666666,
 0.42857142857142855,
 0.75,
 0.6,
 0.5454545454545454,
 0.6666666666666666,
 0.5454545454545454]
 

3) Graph.edge_betweenness() 返回边的中间中心度、Graph.betweenness() 返回顶点的中间中心度

In [185]:
g_5.edge_betweenness()
Out[185]:
[6.0, 6.0, 4.0, 2.0, 4.0, 3.0, 4.0, 3.0, 4.0]
In [186]:
g_5.get_edgelist()
Out[186]:
[(0, 1), (0, 2), (2, 3), (3, 4), (2, 4), (2, 5), (0, 5), (3, 6), (5, 6)]
In [187]:
ebs = g_5.edge_betweenness()
max_eb = max(ebs)
In [188]:
max_eb
Out[188]:
6.0
In [191]:
# 返回中心度最大的边
[g.es[idx].tuple for idx,eb in enumerate(ebs) if eb==max_eb]
Out[191]:
[(0, 1), (2, 3)]
In [190]:
g_5.betweenness()
Out[190]:
[5.0, 0.0, 5.5, 1.5, 0.0, 2.5, 0.5]
 

4) Graph.evcent():点的特征向量中心度

In [194]:
g_5.evcent()
Out[194]:
[0.7111995450108003,
 0.24860112203602627,
 1.0,
 0.7513988779639744,
 0.6122047310756776,
 0.7860026990612522,
 0.5374015770252261]
In [195]:
plot(g_5)
Out[195]:
 
 

五、Querying vertices and edges based on attributes

In [198]:
g_5.degree(), g_5.maxdegree()
Out[198]:
([3, 1, 4, 3, 2, 3, 2], 4)
In [199]:
g_5.vs.select(_degree = g_5.maxdegree())['name']
Out[199]:
['Claire']
In [202]:
g_5.vs.select(_degree = g_5.maxdegree())
Out[202]:
<igraph.VertexSeq at 0x5cabef8>
 

select(self, *args, **kwds) 可以传位置参数和关键字参数

 

1)参数为位置参数

In [203]:
#若第一个位置参数为None,返回一个空的序列
seq = g.vs.select(None)
In [204]:
len(seq)
Out[204]:
0
In [207]:
#若第一个位置参数为可调用对象(函数,方法,或者类似函数可调用的对象),若返回结果为True,则包含在返回序列中
graph = Graph.Full(10)
In [208]:
print graph
 
IGRAPH U--- 10 45 --
+ edges:
 0 --  1  2  3  4  5  6  7  8  9    5 --  0  1  2  3  4  6  7  8  9
 1 --  0  2  3  4  5  6  7  8  9    6 --  0  1  2  3  4  5  7  8  9
 2 --  0  1  3  4  5  6  7  8  9    7 --  0  1  2  3  4  5  6  8  9
 3 --  0  1  2  4  5  6  7  8  9    8 --  0  1  2  3  4  5  6  7  9
 4 --  0  1  2  3  5  6  7  8  9    9 --  0  1  2  3  4  5  6  7  8
In [209]:
only_odd_vertices = graph.vs.select(lambda vertex: vertex.index % 2 ==1)
In [210]:
len(only_odd_vertices)
Out[210]:
5
In [222]:
#若参数是可迭代的对象(列表,生成器,其他可迭代对象等),该对象必须返回整数序列,vertex的ID与返回的整数序列如有匹配上的,则包含在返回的序列中
seq = graph.vs.select([2,3,7])
In [223]:
len(seq)
Out[223]:
3
In [224]:
[v.index for v in seq]
Out[224]:
[2, 3, 7]
In [232]:
seq = seq.select([0,2]) #调用select的对象可以不必是Graph对象的完整的VexSeq
In [226]:
[v.index for v in seq]
Out[226]:
[2, 7]
In [233]:
seq = graph.vs.select([2,3,7,'foo',4.5]) #只能是范围内的整数,字符串,浮点数会跳过,超过范围的整数,则报错
In [234]:
len(seq)
Out[234]:
3
In [240]:
#若第一个位置参数为整数,则后面的参数也必须为整数,相当于传了一个整数类型的list
seq = graph.vs.select(2,3,7)
In [241]:
len(seq)
Out[241]:
3
 

2) 关键字参数

 

用来过滤属性或者图的结构性质,关键字包含两部分,一部分是属性或者结构性质的名字,另一部分过滤的操作符,后者可省略,此时默认为等于。因Python语法限制,参数中出现的操作符只能有=,不能出现>,<,in等。如下是可能的关键字:

 
Keyword argumentMeaning
name_eq 属性/性质的值必须 等于 关键字参数的值
name_ne ......不等于......
name_lt ......小于......
name_le ......小于等于......
name_gt ......大于......
name_ge ......大于等于......
name_in ......包含......,此时参数必须是一个序列
name_notin ......不包含......,此时参数必须是一个序列
In [243]:
print g_5
 
IGRAPH UN-- 7 9 --
+ attr: age (v), gender (v), name (v), is_formal (e)
+ edges (vertex names):
 Alice -- Bob, Claire, Frank
   Bob -- Alice
Claire -- Alice, Dennis, Esther, Frank
Dennis -- Claire, Esther, Geprge
Esther -- Claire, Dennis
 Frank -- Alice, Claire, Geprge
Geprge -- Dennis, Frank
In [244]:
g_5.vs['age']
Out[244]:
[25, 31, 18, 47, 22, 23, 50]
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]:
[0, 2, 4, 5]
 

若属性和结构性质的重名了,会出现歧义,此时如果关键字指的是结构性质需要在前面加_,即_name。否则会认为是属性名字

In [252]:
g_5.get_edgelist()
Out[252]:
[(0, 1), (0, 2), (2, 3), (3, 4), (2, 4), (2, 5), (0, 5), (3, 6), (5, 6)]
In [253]:
g_5.degree()
Out[253]:
[3, 1, 4, 3, 2, 3, 2]
In [256]:
seq_stru = g_5.vs(_degree_gt=2)
[v.index for v in seq_stru]
Out[256]:
[0, 2, 3, 5]
In [258]:
seq_stru = g_5.vs(degree_gt=2) #没有degree属性,报错
[v.index for v in seq_stru]
 
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-258-b126822cd4e0> in <module>()
----> 1seq_stru = g_5.vs(degree_gt=2) #没有degree属性,报错
      2 [v.index for v in seq_stru]

C:\Anaconda2\lib\site-packages\igraph\__init__.pyc in __call__(self, *args, **kwds)
   3511         This method simply passes all its arguments to L{VertexSeq.select()}.
   3512         """
-> 3513return self.select(*args, **kwds)
   3514 
   3515 ##############################################################

C:\Anaconda2\lib\site-packages\igraph\__init__.pyc in select(self, *args, **kwds)
   3500                 values = getattr(vs.graph, attr[1:])(vs)
   3501             else:
-> 3502values = vs[attr]
   3503             filtered_idxs=[i for i, v in enumerate(values) if func(v, value)]
   3504             vs = vs.select(filtered_idxs)

KeyError: 'Attribute does not exist'
In [259]:
[vs.degree() for vs in g_5.vs]
Out[259]:
[3, 1, 4, 3, 2, 3, 2]
 

六、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 [ ]:
 
posted @ 2017-10-26 14:55  一川  阅读(2585)  评论(0编辑  收藏  举报