igraph无效顶点Id

时间:2016-01-23 02:02:07

标签: python-2.7 cluster-analysis igraph hierarchical-clustering

我尝试使用以下代码运行igraph的快速贪婪社区检测算法:

G = Graph()

L = []
V = []
for row in cr:

    try:
        l = []
        source = int((row[0]).strip())
        target = int((row[1]).strip())
        weight = int((row[2]).strip())
        l.append(source)
        l.append(target)

        if l not in L:
            L.append(l)

        if source not in V:
            V.append(source)

        if target not in V:
            V.append(target)
    except ValueError:
        print "Value Error"
        continue

    if weight == 1:
        continue

G.add_vertices(max(V))
G.add_edges(L)
cl = G.community_fastgreedy(weights=weight).as_clustering(10);

但这是我得到的错误:     igraph._igraph.InternalError:type_indexededgelist.c时出错:272:无法添加边,无效的顶点id

我发现了这个:Cannot add edges, Invalid vertex ID in IGraph所以我尝试添加所有顶点,然后是所有边缘,但我仍然遇到错误。

以上代码是否与以下内容完全相同:

tupleMapping = []
for row in cr:
    if int(row[2]) < 10:
        continue

    l = [row[0], row[1], row[2]]
    tupleMapping.append(tuple(l))

g = Graph.TupleList(tupleMapping)
cl = g.community_fastgreedy().as_clustering(20)

我不必明确说出G.community_fastgreedy(权重=体重)吗?

我遇到的另一个问题;当我尝试以下列方式添加更多群集时:

cl = g.community_fastgreedy().as_clustering(10)
cl = g.community_fastgreedy().as_clustering(20)

我得到两个大型集群,其余的集群由一个元素组成。当我尝试使群集大小为5/10/20时,会发生这种情况,是否有任何方法可以使群集更均等地划分?我的数据集需要2个以上的集群。

这是我尝试从csv文件中读取的数据的一小部分,以便我可以生成图形,然后运行社区检测算法:     202,580,11     87,153,7     227,459,6     263,524,11

感谢。

1 个答案:

答案 0 :(得分:3)

没错,第二个代码也是这样。在第一个示例中,问题是当您添加边时,您将引用igraph的内部顶点ID,它始终从0开始,直到N-1。无论您自己的顶点名称是整数,您都需要将它们转换为igraph顶点ID。

此处igraph.Graph.TupleList()方法更方便。但是,您需要指定元组的第三个元素是权重。您可以通过weights = Trueedge_attrs = ['weight']参数来执行此操作:

import igraph

data = '''1;2;34
1;3;41
1;4;87
2;4;12
4;5;22
5;6;33'''

L = set([])

for row in data.split('\n'):
    row = row.split(';')
    L.add(
        (row[0].strip(), row[1].strip(), int(row[2].strip()))
    )

G = igraph.Graph.TupleList(L, edge_attrs = ['weight'])

然后,您可以创建字典以在igraph顶点ID和原始名称之间进行转换:

vid2name = dict(zip(xrange(G.vcount()), G.vs['name']))
name2vid = dict((name, vid) for vid, name in vid2name.iteritems())

然而,第一个并不是那么需要,因为你总是可以使用G.vs[vid]['name']

对于fastgreedy,我认为你应该指定权重,至少文档不会告诉它是否自动考虑名为weight的属性,如果这样的属性存在。

fg = G.community_fastgreedy(weights = 'weight')
fg_clust_10 = fg.as_clustering(10)
fg_clust_20 = fg.as_clustering(20)

如果fastgreedy只给你2个大型集群,我只能建议尝试其他社区检测方法。实际上,您可以尝试在合理时间内运行的所有这些(取决于图表的大小),然后比较它们的结果。另外,因为你有一个加权图,你可以看看moduland method family,它没有在igraph中实现,但有很好的文档,你可以设置相当复杂的设置。

编辑:OP的评论表明原始数据描述了有向图。 fastgreedy算法无法考虑方向,如果在有向图上调用则会出错。这就是为什么在我的例子中我创建了一个无向igraph.Graph()对象。如果你想运行其他方法,其中一些可能能够处理定向网络,你应该首先创建一个有向图:

G = igraph.Graph.TupleList(L, directed = True, edge_attrs = ['weight'])
G.is_directed()
# returns True

要快速运行,请将图表转换为无向图。由于边缘具有权重属性,因此需要指定当同一对顶点之间的2个相对方向边缘折叠到一个无向边时应该执行的操作。您可以使用权重执行许多操作,例如取平均值,较大值或较小值等。例如,要使组合边具有原始边的平均权重:

uG = G.as_undirected(combine_edges = 'mean')
fg = uG.community_fastgreedy(weights = 'weight')

重要提示:请注意,在此操作中,以及添加或删除顶点或边时,igraph会重新索引顶点和边,因此如果您知道顶点标识x对应于您的原始标识{{1重新编制索引后,这将不再有效,您需要重新创建yname2vid词典。