从Pandas数据框创建igraph图

8

我有以下Pandas DataFrame,包含如下的边缘列表:

        name1              name2    weight
0  $hort, Too  Alexander, Khandi  0.083333
1  $hort, Too             B-Real  0.083333

我想从 Pandas 数据帧中创建一个 igraph 对象(而不是从文件中创建)。由于图形过大,因此我无法将其转换为邻接矩阵。如何处理?
5个回答

11

igraph需要元组,pandas提供.itertuples()用于一对:

(source, target, weight(optional))

假设你的数据框命名为“df”,你可以通过以下方式从pandas数据框中获取带有权重的有向图对象:
import pandas as pd
import igraph as ig

g = ig.Graph.TupleList(df.itertuples(index=False), directed=True, weights=True, edge_attrs="weight")

根据https://igraph.org/python/doc/igraph.Graph-class.html#TupleList,weights是指定图形加权的替代方法。如果将weights设置为true且未给出edge_attrs,则假定edge_attrs为["weight"],并且igraph将解析每个项的第三个元素作为边权重。因此,在您的情况下,不需要"edge_attrs=",但我添加它只是为了更通用的解决方案。

太好了!我找了很久才找到这个答案。有一个纠正:在g = ig.Graph.TupleList(df.itertuples(index=False), directed=True, weights=True, edge_attrs="weight")中,应该将weights=False而不是True。否则我会出现错误。 - Alexander Chervov
你遇到了哪个错误?Kaggle的示例没有显示任何错误或设置weight=False的原因(除非你的数据框中没有weight列)。 - Vega

10

我也在寻找igraph中与 Networkx from_pandas_dataframe 函数等效的函数,我发现使用 Graph.TupleList() 是最好的解决方案。因此,基本上你需要从3个 pandas 列创建一个元组,然后使用这个函数来创建网络。

tuples = [tuple(x) for x in df.values]
Gm = igraph.Graph.TupleList(tuples, directed = True, edge_attrs = ['weight'])

在这种情况下,igraph分配的顶点编号如何对应于数据框中的原始名称? - user3450049
每个顶点都将被赋予一个名为“name”的属性,该属性对应于您的DataFrame中的原始名称,即“name1”和“name2”。 您可以使用{v['name']: v.index for v in list(Gm.vs)}获取igraph顶点索引到名称的映射。 - rlchqrd

1
我通常是按照以下方式进行操作,尽管我经常会出现重复的边缘,这就是为什么我的权重容易改变(我假设你的pandas数据框命名为df):
import igraph

edgelist = []
weights = []
for i in df.index():
    edge = (df.ix[i, 'name1'], df.ix[i, 'name2'])
    if edge not in edgelist:
        edgelist.append(edge)
        weights.append(1)
    else:
        weights[edgelist.index(edge)] += 1

G = Graph()
G.add_edges(edgelist)
G.es['weight'] = weights

在“for i in df.index():”这行中,您应该删除括号。 - TheCodeNovice

1
仅是草图/伪代码,但是怎么样:

for i, row in df.iterrows():
    graph.add_edge(row.name1, row.name2, weight=row.weight)

当我使用这段代码时,我遇到了这个错误:AttributeError: 'tuple' object has no attribute 'node1'。 - Rio
@EmmaNej 谢谢你提醒。看起来iterrows返回的是一个元组,所以你需要将其拆开。一种方法是在for循环中指定索引和行对象。我已经更新了我的答案示例以反映这一点。 - kuanb
是的,我也尝试过了,但仍然出现错误!TypeError: 未绑定的方法add_edge()必须使用Graph实例作为第一个参数进行调用(而不是int64实例)。 - Rio
好的,看起来igraph有一个不同的add_edge实现,所以我会查找如何使用graph.add_edge()的文档。我会看一下这个教程:http://igraph.org/python/doc/tutorial/tutorial.html 可能想尝试一些类似于g.add_edges((2,0))的东西,其中20是from和to值的id。 - kuanb

1
我正在使用 igraph 版本 0.9.6,似乎有一种直接的方法可以做到这一点:
import igraph as ig
import pandas as pd

mydata = pd.DataFrame({'name1': ['$hort, Too', '$hort, Too'], 
                   'name2': ['Alexander, Khandi', 'B-Real'], 
                   'weight': [0.083333, 0.083333]})
mygraph = ig.Graph.DataFrame(mydata)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接