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

时间:2017-03-02 14:31:43

标签: python pandas graph 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
    ...
    
  2. 然后从表/电子表格加载边缘,使用与节点电子表格的列ID中相同的节点名称,通常有四列(目标,来源,重量和类型): / p>

    Target;Source;Weight;Type
    per1;per2;3;Undirected
    per3;per4;2;Undirected
    ...
    
  3. 这是我拥有的两个数据帧,我想在Python中加载。阅读关于NetworkX,似乎不太可能将两个表(一个用于节点,一个用于边缘)加载到同一个图表中,我不确定最好的方法是什么:

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

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

3 个答案:

答案 0 :(得分:17)

使用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的参数顺序为changed(G, values, name=None)

使用上面的例子:

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

答案 1 :(得分:1)

这里的答案基本相同,但已更新,并填充了一些详细信息。我们将以基本相同的设置开始,但是这里将没有节点索引,仅是地址@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类型,但是如果您不需要它,则可以通过显而易见的方式将其设置为其他类型。

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

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

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

答案 2 :(得分:0)

一句话:

from_pandas_dataframe在nx 2中不起作用,请参阅此

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

我认为在nx 2.0中它是这样的:

G = nx.from_pandas_edgelist(edges, source = "Source", target = "Target")
相关问题