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 [ ]: