从 Pandas DataFrame 创建 NetworkX 多重图

12

更新:
如所写,问题与 Networkx 版本 < 2.0 相关。方法 from_pandas_dataframe 已被删除
为在 Networkx >= 2.0 中完成相同任务,请参阅已接受答案的更新部分。

尝试使用 networkx 的 from_pandas_dataframe 从 pandas DataFrame 创建一个 MultiGraph() 实例。在下面的示例中我做错了什么?

In [1]: import pandas as pd
        import networkx as nx

        df = pd.DataFrame([['geneA', 'geneB', 0.05, 'method1'],
                           ['geneA', 'geneC', 0.45, 'method1'],
                           ['geneA', 'geneD', 0.35, 'method1'],
                           ['geneA', 'geneB', 0.45, 'method2']], 
                           columns = ['gene1','gene2','conf','type'])

使用默认的nx.Graph()进行第一次尝试:

In [2]: G= nx.from_pandas_dataframe(df, 'gene1', 'gene2', edge_attr=['conf','type'], 
                                    create_using=nx.Graph())

作为非MultiGraph(),我缺少其中一个重复的边。
In [3]: G.edges(data=True)
Out[3]: [('geneA', 'geneB', {'conf': 0.45, 'type': 'method2'}),
         ('geneA', 'geneC', {'conf': 0.45, 'type': 'method1'}),
         ('geneA', 'geneD', {'conf': 0.35, 'type': 'method1'})]

使用MultiGraph():
In [4]: MG= nx.from_pandas_dataframe(df, 'gene1', 'gene2', edge_attr=['conf','type'], 
                             create_using=nx.MultiGraph())

这个:

TypeError                                 Traceback (most recent call last)
<ipython-input-49-d2c7b8312ea7> in <module>()
----> 1 MG= nx.from_pandas_dataframe(df, 'gene1', 'gene2', ['conf','type'], create_using=nx.MultiGraph())

/usr/lib/python2.7/site-packages/networkx-1.10-py2.7.egg/networkx/convert_matrix.pyc in from_pandas_dataframe(df, source, target, edge_attr, create_using)
    209         # Iteration on values returns the rows as Numpy arrays
    210         for row in df.values:
--> 211             g.add_edge(row[src_i], row[tar_i], {i:row[j] for i, j in edge_i})
    212 
    213     # If no column names are given, then just return the edges.

/usr/lib/python2.7/site-packages/networkx-1.10-py2.7.egg/networkx/classes/multigraph.pyc in add_edge(self, u, v, key, attr_dict, **attr)
    340             datadict.update(attr_dict)
    341             keydict = self.edge_key_dict_factory()
--> 342             keydict[key] = datadict
    343             self.adj[u][v] = keydict
    344             self.adj[v][u] = keydict

TypeError: unhashable type: 'dict'

问题 如何从pandas数据框实例化一个MultiGraph()

2个回答

13

Networkx < 2.0:
这是一个bug,我在GitHub上提了一个问题,在我按照建议所做的编辑后:

它将convert_matrix.py的第211行更改为:

g.add_edge(row[src_i], row[tar_i], attr_dict={i:row[j] for i, j in edge_i})

那次变更的结果:(已经被合并)

MG= nx.from_pandas_dataframe(df, 'gene1', 'gene2', edge_attr=['conf','type'], 
                                 create_using=nx.MultiGraph())

MG.edges(data=True)
[('geneA', 'geneB', {'conf': 0.05, 'type': 'method1'}),
         ('geneA', 'geneB', {'conf': 0.45, 'type': 'method2'}),
         ('geneA', 'geneC', {'conf': 0.45, 'type': 'method1'}),
         ('geneA', 'geneD', {'conf': 0.35, 'type': 'method1'})]

Networkx >= 2.0:
在这种格式的数据框中(边列表),使用from_pandas_edgelist函数。

MG= nx.from_pandas_edgelist(df, 'gene1', 'gene2', edge_attr=['conf','type'], 
                             create_using=nx.MultiGraph())

MG.edges(data=True)
MultiEdgeDataView([('geneA', 'geneB', {'conf': 0.05, 'type': 'method1'}),
                   ('geneA', 'geneB', {'conf': 0.45, 'type': 'method2'}),
                   ('geneA', 'geneC', {'conf': 0.45, 'type': 'method1'}), 
                   ('geneA', 'geneD', {'conf': 0.35, 'type': 'method1'})])

这是被接受的答案,但根据文档:https://pelegm-networkx.readthedocs.io/en/latest/reference/generated/networkx.MultiDiGraph.add_edge.html 当我创建边缘时,我可以指定平行边的键,然后也可以指定属性。通过这个答案,我看到我可以设置属性。那么我该如何指定键呢? - user305883

4

这是一个很好的问题。我尝试以不同的方式构建您的MultiGraph(),只使用三到四列:

MG = nx.MultiGraph()

MG.add_weighted_edges_from([tuple(d) for d in df[['gene1','gene2','conf']].values])

这个正确的返回值是MG.edges(data=True)
[('geneA', 'geneB', {'weight': 0.05}), ('geneA', 'geneB', {'weight': 0.45}), ('geneA', 'geneC', {'weight': 0.45}), ('geneA', 'geneD', {'weight': 0.35})]

我尝试使用您的from_pandas_dataframe方法仅使用三列,但它无法工作。
MG = nx.from_pandas_dataframe(df, 'gene1', 'gene2', edge_attr='conf', create_using=nx.MultiGraph())

这会返回与您遇到的相同的错误。我不知道它是一个bug还是那个方法不支持多个权重类型的MultiGraph()。与此同时,您可以使用上述解决方法构建您的MultiGraph,至少只有一种权重类型。希望能对您有所帮助。


我现在会使用这个解决方法,谢谢。很想知道是否有人遇到过类似的错误。 - Kevin
@Kevin...两年后,我遇到了同样的错误。在我的情况下,我试图创建一个MultiDiGraph(),但是和你一样遇到了相同的错误。这个答案也解决了我的问题。 - Sos

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