如何才能做到像gephi那样社区划分可视化呢?

gephi是一个社会网络分析可视化的软件,其大部分代码是用java实现的。
而我在学习的时候,是用python构图;
在这里,我可以推荐两种python画图包,networkx和igraph。
前期的学习,我是学习networkx,但其缺乏较好的画图布局算法。
后来,在队友的推荐下,我学会使用igraph画图,这个是我画的其中一个图:

如何才能做到像gephi那样社区划分可视化呢?_第1张图片
至于如何做到这样的效果呢,步骤如下:

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列表是用于记录划分社区结果,一般格式如下,
列表的长度代表划分社区的个数,列表的每一个小列表代表每一个社区所含节点的情况:
如何才能做到像gephi那样社区划分可视化呢?_第2张图片

将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效果,可以补充上面的不足。

你可能感兴趣的:(如何才能做到像gephi那样社区划分可视化呢?)