在python igraph中选择簇和顶点的数量

时间:2016-06-15 19:27:08

标签: python graph cluster-analysis graph-theory igraph

我有一个完整加权图,如下图所示:

enter image description here

目标: 我的目标是能够使用python的iGraph实现选择每个集群中的簇数和顶点数

我到目前为止所做的一切:

import igraph
import cairo
import numpy as np

# Import data (see below, I've included this file)
graph2 = igraph.Graph.Read_Ncol('10_graph.ncol')

# Assigns weights to weights1
weights1 = graph2.es["weight"]

# Converts it to undirected graph
graph2.to_undirected()

# 'graph2.to_undirected()' strips the graph of its weights
# so we restore them to the "weight" attribute after
graph2.es["weight"] = weights1

# Reduces the number of significant figures in each edge label
graph2.es["label"] = np.around(weights1, 2)

# Label all the vertices
graph2.vs["label"] = range(1, 11)

# Things I've tried: (uncomment only one at a time)
# Both return non-clustered graphs.
#community = graph2.community_spinglass(weights1)
community = graph2.community_leading_eigenvector(weights=graph2.es["weight"], clusters=3)
igraph.plot(community)

如果运行上面的代码,则输出上面的图像。对于我所包含的社区查找算法,您可以获得相同的图像。我已经注释掉其中一个,所以如果你想使用另一个,请继续取消注释#community = graph2.community_spinglass(weights1)

问题:

  • 看起来没有一个图表按我希望的方式聚集。
    • 我传递weights=graph2.es["weight"],与图表中的顶点对应的权重列表。
    • 我还明确地将clusters=3传递给community_leading_eigenvector()
    • 我仍然没有根据此图表的边缘权重进行任何聚类。
    • 如何通过颜色或位置绘制正确的聚类,或者iGraph处理聚类的区别?
  • 我无法找到有关如何选择每个群集中顶点数量的任何官方文档。
    • 是否有办法(甚至是环形交叉路口)选择每个群集中的顶点数量?它不一定是完全,而是近似值。

10_graph.ncol

这是我导入以形成图形的.ncol文件。

10_graph.ncol =

0 1 0.859412093436
0 2 0.696674188289
0 3 0.588339776278
0 4 0.5104097013
0 5 0.462457938906
0 6 0.427462387255
0 7 0.40350595007
0 8 0.382509071902
0 9 0.358689934558
1 2 0.912797848896
1 3 0.78532402562
1 4 0.681472223562
1 5 0.615574694967
1 6 0.567507619872
1 7 0.534715438785
1 8 0.506595029246
1 9 0.474297090248
2 3 0.941218154026
2 4 0.83850483835
2 5 0.759542327211
2 6 0.70025846718
2 7 0.659110815342
2 8 0.624313042633
2 9 0.584580479234
3 4 0.957468322138
3 5 0.886571688707
3 6 0.821838040975
3 7 0.772665012468
3 8 0.730820137423
3 9 0.684372167781
4 5 0.97372551117
4 6 0.92168855187
4 7 0.870589109091
4 8 0.823583870451
4 9 0.772154420843
5 6 0.98093419661
5 7 0.941236624882
5 8 0.895874086289
5 9 0.843755656833
6 7 0.985707938753
6 8 0.9523988462
6 9 0.906031710578
7 8 0.988193527182
7 9 0.955898136286
8 9 0.988293873257

1 个答案:

答案 0 :(得分:0)

这两种方法都只返回一个集群。这告诉我你的顶点之间没有明显的分离:它们只是一个很大的纠结,所以没有合理的方法将它们分开。

如果我编辑边缘权重以获得清晰的分色,例如下面的10_g2.ncol,则聚类算法会对顶点进行划分。

在第一次,这并没有产生我预期的群体。我在顶点集{0,1,2,3},{4,5,6}和{7,8,9}中放置了高权重,并在不同集之间设置了低权重。但是spinglass将它拆分为{0,1,2,5,6},{3,4}和{7,8,9},而leading_eigenvector将其拆分为{0,1,2,5,6}和{ 3,4,7,8,9}。

事实证明这是因为to_undirected()改变了边的顺序,所以当你在这个操作之后重新分配边权重时,它会将它们与不同的边相关联。为避免这种情况,您应该指示to_undirected保留边缘属性,例如由

graph2.to_undirected(combine_edges="max")

保留每个边缘属性的最大值(如果在相同顶点之间有多个有向边),或

graph2.to_undirected(combine_edges="first")

只保留第一个看到的值。 (在这种情况下,该方法应该是无关紧要的,因为没有多个边。)

将图表实际拆分为多个群集后,默认的plot方法会按颜色区分它们。您也可以使用community.subgraph(i)来获取i th 集群的子图,然后绘制它。

如何控制集群数量?如您所知,leading_eigenvalue方法对于所需数量的聚类具有clusters参数,但它显然比实际规则更具指导性:给clusters=3仅产生1个数据集群,以及2与我的集群。

您可以使用返回VertexDendrogram而非群集的方法更精确地控制群集数量,例如`community_edge_betweenness。

com3 = graph2.community_edge_betweenness(clusters=3, directed=False, weights="weight")

要获得包含n群集的群集,请致电com3.as_clustering(n),为我的所有测试提供完全n个群集。

他们不一定是好的集群:

In [21]: print(com3.as_clustering(3))
Clustering with 10 elements and 3 clusters
[0] 0
[1] 1, 2, 3, 4, 5, 7, 8, 9
[2] 6

In [22]: print(com3.as_clustering(4))
Clustering with 10 elements and 4 clusters
[0] 0
[1] 1, 2, 3, 4, 5, 8, 9
[2] 6
[3] 7

In [23]: print(com3.as_clustering(5))
Clustering with 10 elements and 5 clusters
[0] 0
[1] 1, 3, 5
[2] 2, 4, 8, 9
[3] 6
[4] 7

In [24]: print(com3.as_clustering(6))
Clustering with 10 elements and 6 clusters
[0] 0
[1] 1, 3, 5
[2] 2, 8, 9
[3] 4
[4] 6
[5] 7

返回VertexDendrograms的其他方法是community_walktrapcommunity_fastgreedy。对于这个特殊的例子,它们似乎都表现得更好,IMO。

In [25]: com5 = graph2.community_walktrap(weights='weight')

In [26]: com6 = graph2.community_fastgreedy(weights='weight')

In [27]: print(com5.as_clustering(3))
Clustering with 10 elements and 3 clusters
[0] 0, 1, 2, 5, 6
[1] 3, 4
[2] 7, 8, 9

In [32]: print(com6.as_clustering(3))
Clustering with 10 elements and 3 clusters
[0] 0, 1, 2, 5, 6
[1] 3, 4
[2] 7, 8, 9

以下是我使用的杂色加权。

10_g2.ncol:

0 1 0.91
0 2 0.92
0 3 0.93
0 4 0.04
0 5 0.05
0 6 0.06
0 7 0.07
0 8 0.08
0 9 0.09
1 2 0.94
1 3 0.95
1 4 0.14
1 5 0.15
1 6 0.16
1 7 0.17
1 8 0.18
1 9 0.19
2 3 0.96
2 4 0.01
2 5 0.02
2 6 0.03
2 7 0.04
2 8 0.05
2 9 0.06
3 4 0.01
3 5 0.01
3 6 0.01
3 7 0.01
3 8 0.01
3 9 0.01
4 5 0.97
4 6 0.92
4 7 0.05
4 8 0.04
4 9 0.08
5 6 0.98
5 7 0.12
5 8 0.08
5 9 0.08
6 7 0.07
6 8 0.06
6 9 0.06
7 8 0.98
7 9 0.95
8 9 0.98