将 NetworkX 节点属性转化为 Pandas 数据框列

10

我有一个以下创建的Networkx图,名为G

import networkx as nx
G = nx.Graph()
G.add_node(1,job= 'teacher', boss = 'dee')
G.add_node(2,job= 'teacher', boss = 'foo')
G.add_node(3,job= 'admin', boss = 'dee')
G.add_node(4,job= 'admin', boss = 'lopez')

我希望能够将node编号、attributesjobboss存储在pandasdataframe的不同列中。我尝试使用下面的代码实现,但是它生成了一个只有两列的dataframe,其中一列是node编号,另一列包含所有attributes
graph = G.nodes(data = True)
import pandas as pd
df = pd.DataFrame(graph)

df
Out[19]: 
    0                                      1
0  1  {u'job': u'teacher', u'boss': u'dee'}
1  2  {u'job': u'teacher', u'boss': u'foo'}
2  3    {u'job': u'admin', u'boss': u'dee'}
3  4  {u'job': u'admin', u'boss': u'lopez'}

注意:我知道 NetworkX 有一个 to_pandas_dataframe 函数,但它不能提供我要寻找的输出 dataframe
5个回答

29

这是一个简短的语句。

pd.DataFrame.from_dict(dict(graph.nodes(data=True)), orient='index')

2
这是更符合Python风格的答案。 - Ahmed Al-haddad
然而,如果节点没有属性,则无法正常工作,那么你将得到一个空的DataFrame。 - Mitar
@Mitar 如果一个图形没有属性,预期的输出会是什么?只有索引的数据框? - Ufos
1
最好只索引。 - Mitar

5
我认为这更简单:
pandas.DataFrame.from_dict(graph.nodes, orient='index')

无需转换成其他字典。


1
然而,如果节点没有属性,则无法正常工作,那么你将得到一个空的DataFrame。 - Mitar
我知道这个答案晚了2年,但它应该被接受为正确答案。 - Ben Lindsay

2
我不知道你的数据有多具代表性,但修改我的代码以适用于你的实际网络应该很简单:
In [32]:
data={}
data['node']=[x[0] for x in graph]
data['boss'] = [x[1]['boss'] for x in graph]
data['job'] = [x[1]['job'] for x in graph]
df1 = pd.DataFrame(data)
df1

Out[32]:
    boss      job  node
0    dee  teacher     1
1    foo  teacher     2
2    dee    admin     3
3  lopez    admin     4

这里我所做的就是从图形数据构建一个字典,pandas接受以列名为键、数据为值的字典作为数据,数据必须是类似数组的结构,此处是值的列表。

一种更加动态的方法:

In [42]:
def func(graph):
    data={}
    data['node']=[x[0] for x in graph]
    other_cols = graph[0][1].keys()
    for key in other_cols:
        data[key] = [x[1][key] for x in graph]
    return data
pd.DataFrame(func(graph))

Out[42]:
    boss      job  node
0    dee  teacher     1
1    foo  teacher     2
2    dee    admin     3
3  lopez    admin     4

谢谢你的解决方案。我不理解的唯一部分是 x[0] for x in graph。我知道 graph 是一个列表,但在 graph 中的 xx[0] 中发生了什么? - BeeGee
你有一个元组的列表,元组的第一个元素是节点值,因此 x[0],第二个元素是字典 x[1] - EdChum
有一个错误。应该是 def func(graph): - MERose

1

我更新了这个解决方案,使其适用于我更新的NetworkX版本(2.0),并想与大家分享。我还让函数返回了一个Pandas DataFrame。

def nodes_to_df(graph):
    import pandas as pd
    data={}
    data['node']=[x[0] for x in graph.nodes(data=True)]
    other_cols = graph.nodes[0].keys()
    for key in other_cols:
        data[key] = [x[1][key] for x in graph.nodes(data=True)]
    return pd.DataFrame(data)

0
我用一个 字典推导式 解决了这个问题。
d = {n:dag.nodes[n] for n in dag.nodes}

df = pd.DataFrame.from_dict(d, orient='index')

你的字典d将节点n映射到dag.nodes[n]。 该字典dag.nodes[n]的每个值本身都是一个字典,包含所有属性:{attribute_name:attribute_value}

因此,你的字典d的形式为:

{node_id : {attribute_name : attribute_value} }

我看到的优点是您不需要知道属性的名称。

如果您想要将节点ID放在列中而不是索引中,您可以添加以下命令:

df.reset_index(drop=False, inplace=True)

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