gephi是一个社会网络分析可视化的软件,其大部分代码是用java实现的。
而我在学习的时候,是用python构图;
在这里,我可以推荐两种python画图包,networkx和igraph。
前期的学习,我是学习networkx,但其缺乏较好的画图布局算法。
后来,在队友的推荐下,我学会使用igraph画图,这个是我画的其中一个图:
1.导入数据:
导入数据,我基本模仿的是gephi软件的导入格式,即source ,target,weight,具体如下:
我使用的是足球俱乐部的样例,每个结点代表了参加美国2000年橄榄球赛季的高效代表队,
连接两个结点之间的边表示相应两支球队之间至少曾有过一场比赛。
规模:77个节点,615条边。
出处:M.Girvan and M.E.J.Newman,Proc.Natl.Acad.Sci.USA 99,7821-7826(2002)
2.预处理数据:
导入数据后,构建好邻接矩阵。然后创建igraph中的g对象,利用矩阵为g对象添加点和边,具体如下 :
g=Graph(1)
g.add_vertices(len(matrix)-1)
weights=[]
for i in range(len(matrix)):
for j in range(len(matrix)):
if matrix[i][j]>0:
g.add_edge(i,j)
weights.append(matrix[i][j])
3.社区划分算法:
igraph中提供了很多种社区划分的算法,
例如BGLL,walktrap,fastgreedy,LPA算法等,以下是这些算法的使用规则:
BGLL:
result=g.community_multilevel(weights)
walktrap:
se = g.community_walktrap(weights, steps=4)
ss = se.as_clustering()
result = [[]for i in range(ss.__len__())]
for i in range(0, ss.__len__(), 1):
result[i] = (ss.__getitem__(i))
fastgreedy :(只能处理无向图,即对称矩阵)
se = g.community_fastgreedy(weights)
ss = se.as_clustering()
Q = ss.recalculate_modularity()
result = [[]for i in range(ss.__len__())]
for i in range(0, ss.__len__(), 1):
result[i] = (ss.__getitem__(i))
LPA:
se=g.community_label_propagation(weights=weights)
ss=se.as_clustering()
result=[[]for i in range(se.__len__()) ]
for i in range(0,se.__len__(),1):
result[i]=(se.__getitem__(i))
result列表是用于记录划分社区结果,一般格式如下,
列表的长度代表划分社区的个数,列表的每一个小列表代表每一个社区所含节点的情况:
将result列表转化为单一列表,其记录每一个点所在的社区,转化的代码如下:
listresult = [0 for i in range(esult.len())]
for i in range(0, result.len(), 1):
for j in range(0, self.result[i].len(), 1):
listresult[self.result[i][j]] = i
效果如下:
4.igraph画图:
igraph提供一个Polt类,专门为画图而用 。
而刚刚的listresult用于画图区别颜色的,具体的代码如下:
g = g.simplify(g) #去除重复边
layout = g.layout_graphopt()#选择图的布局算法,
除此还有kk弹簧算法,fr力导向算法等
#为每个点规划大小尺寸,若为重要的点,可以画大一点,最后形成一个列表
vs = 30
if vex > 50:
vs = 20
If vex > 200:
vs = 15
if vex > 500:
vs = 10
if vex > 1000:
vs = 5
Vsize=[]
for i in range(0,vex,1):
If i in top:
Vsize.append(vs*2)
else:
Vsize.append(vs)
#接着为每个点贴上标签
label=ReadLable(labelfile)
for i in label:
labelresult.append(label[i])
g.vs["label"]=labelresult
#创建Polt类
p = Plot()
p.background = "#ffffff" #将背景改为白色,默认是灰色网格
p.add(g,
bbox=(50, 50, 550, 550), #设置图占窗体的大小,默认是(0,0,600,600)
layout =layout, #图的布局
vertex_size=Vsize, #点的尺寸
edge_width=0.5,edge_color="grey", #边的宽度和颜色,建议灰色,比较好看
vertex_label_size=10 #点标签的大小
vertex_color = [color_dict[i % 50] for i in listresult]) #为每个点着色
p.save("/home/quincy/SNA.png") #将图保存到特定路径,igraph只支持png和pdf
p.remove(g) #清除图像
大概按照这样的步骤就可以画出来啦,但这是一个静态图,
不能做到想gephi那样的动态效果。
不过D3JS提供一个力导图的js效果,可以补充上面的不足。