将具有属性和边的节点从 DataFrame 加载到 NetworkX

新手上路,请多包涵

我是使用 Python 处理图形的新手:NetworkX。到目前为止,我一直在使用 Gephi。那里的标准步骤(但不是唯一可能的)是:

  1. 从表格/电子表格加载节点信息;其中一列应该是 ID,其余列是关于节点的元数据(节点是人,所以性别,组……通常用于着色)。喜欢:
    id;NormalizedName;Gender
   per1;Jesús;male
   per2;Abraham;male
   per3;Isaac;male
   per4;Jacob;male
   per5;Judá;male
   per6;Tamar;female
   ...

  1. 然后也从表/电子表格加载边,使用与节点电子表格的列 ID 中相同的节点名称,通常有四列(目标、源、权重和类型):
    Target;Source;Weight;Type
   per1;per2;3;Undirected
   per3;per4;2;Undirected
   ...

这是我拥有的两个数据框,我想在 Python 中加载它们。阅读有关 NetworkX 的文章,似乎不太可能将两个表(一个用于节点,一个用于边)加载到同一个图中,我不确定什么是最好的方法:

  1. 我是否应该仅使用来自 DataFrame 的节点信息创建一个图形,然后添加(追加)来自其他 DataFrame 的边?如果是这样,并且由于 nx.from_pandas_dataframe() 需要有关边缘的信息,我想我不应该使用它来创建节点……我应该只将信息作为列表传递吗?

  2. 我是否应该仅使用来自 DataFrame 的边信息创建一个图形,然后将来自其他 DataFrame 的信息作为属性添加到每个节点?有没有比遍历 DataFrame 和节点更好的方法呢?

原文由 José 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 576
2 个回答

使用 nx.from_pandas_dataframe 从边缘表创建加权图:

 import networkx as nx
import pandas as pd

edges = pd.DataFrame({'source' : [0, 1],
                      'target' : [1, 2],
                      'weight' : [100, 50]})

nodes = pd.DataFrame({'node' : [0, 1, 2],
                      'name' : ['Foo', 'Bar', 'Baz'],
                      'gender' : ['M', 'F', 'M']})

G = nx.from_pandas_dataframe(edges, 'source', 'target', 'weight')

然后使用 set_node_attributes 添加字典中的节点属性:

 nx.set_node_attributes(G, 'name', pd.Series(nodes.name, index=nodes.node).to_dict())
nx.set_node_attributes(G, 'gender', pd.Series(nodes.gender, index=nodes.node).to_dict())

或者遍历图形以添加节点属性:

 for i in sorted(G.nodes()):
    G.node[i]['name'] = nodes.name[i]
    G.node[i]['gender'] = nodes.gender[i]

更新:

nx 2.0 nx.set_node_attributes 参数顺序已 更改(G, values, name=None)

使用上面的示例:

 nx.set_node_attributes(G, pd.Series(nodes.gender, index=nodes.node).to_dict(), 'gender')

nx 2.4G.node[] 被替换为 G.nodes[]

原文由 harryscholes 发布,翻译遵循 CC BY-SA 4.0 许可协议

这是基本上相同的答案,但更新了一些细节。我们将从基本相同的设置开始,但这里不会有节点索引,只有名称来解决@LancelotHolmes 评论并使其更通用:

 import networkx as nx
import pandas as pd

linkData = pd.DataFrame({'source' : ['Amy', 'Bob'],
                  'target' : ['Bob', 'Cindy'],
                  'weight' : [100, 50]})

nodeData = pd.DataFrame({'name' : ['Amy', 'Bob', 'Cindy'],
                  'type' : ['Foo', 'Bar', 'Baz'],
                  'gender' : ['M', 'F', 'M']})

G = nx.from_pandas_edgelist(linkData, 'source', 'target', True, nx.DiGraph())

这里的 True 参数告诉 NetworkX 将 linkData 中的所有属性保留为链接属性。在这种情况下,我将其 DiGraph 类型,但如果您不需要它,那么您可以以显而易见的方式将其设为另一种类型。

现在,由于您需要通过 linkData 生成的节点名称来匹配 nodeData,因此需要将 nodeData 数据帧的索引设置为 name 属性,然后再将其设为字典,以便 NetworkX 2.x 可以加载它作为节点属性。

 nx.set_node_attributes(G, nodeData.set_index('name').to_dict('index'))

这会将整个 nodeData 数据帧加载到一个字典中,其中键是名称,其他属性是该键中的键:值对(即,节点索引是其名称的普通节点属性)。

原文由 Aaron Bramson 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题