NetworkX - 从节点和属性创建图形

时间:2016-12-20 07:14:42

标签: python python-3.x nodes networkx edges

我尝试使用给定节点和属性的networkX制作网络图。每个节点都是唯一的,但它可以与其他节点具有匹配的属性。这些属性将充当所有具有相同属性的节点之间的边缘。

输入(节点和属性)

的示例
Name1   2-s2.0-84905590088, 2-s2.0-84901477890
Name2   2-s2.0-84941169876
Name3   2-s2.0-84958012773
Name4   2-s2.0-84960796474
Name5   2-s2.0-84945302996, 2-s2.0-84953281823, 2-s2.0-84944268402, 2-s2.0-84949478621, 2-s2.0-84947281259, 2-s2.0-84947759580, 2-s2.0-84945265895, 2-s2.0-84945247800, 2-s2.0-84946541351, 2-s2.0-84946051072, 2-s2.0-84942573284, 2-s2.0-84942280140, 2-s2.0-84937715425, 2-s2.0-84943751990, 2-s2.0-84957729558, 2-s2.0-84938844501, 2-s2.0-84934761065
Name6   2-s2.0-84908333808
Name7   2-s2.0-84925879816
Name8   2-s2.0-84940447040, 2-s2.0-84949534001
Name9   2-s2.0-84899915556, 2-s2.0-84922392381, 2-s2.0-84905079505, 2-s2.0-84940931972, 2-s2.0-84893682063, 2-s2.0-84954285577, 2-s2.0-84934934228, 2-s2.0-84926624187
Name10  2-s2.0-84907065810

所以Name5会有很多边连接到具有相同标识符的其他名称。

我不确定这是否是networkX背后的正确理念,或者你是否可以使用这种输入来绘制图形。如果这种方式无法实现,我将如何格式化输入以生成此图形?我无法通过这种方式找到有关使用networkX的任何文档或视频。

1 个答案:

答案 0 :(得分:1)

你问的是可能的。我将您的数据存储在csv文件中 - 请注意我在节点名称后面添加了,并删除了所有空格。

Name1,2-s2.0-84905590088,2-s2.0-84901477890
Name2,2-s2.0-84941169876
Name3,2-s2.0-84958012773
Name4,2-s2.0-84960796474
Name5,2-s2.0-84945302996,2-s2.0-84953281823,2-s2.0-84944268402,2-s2.0-84949478621,2-s2.0-84947281259,2-s2.0-84947759580,2-s2.0-84945265895,2-s2.0-84945247800,2-s2.0-84946541351,2-s2.0-84946051072,2-s2.0-84942573284,2-s2.0-84942280140,2-s2.0-84937715425,2-s2.0-84943751990,2-s2.0-84957729558,2-s2.0-84938844501,2-s2.0-84934761065
Name6,2-s2.0-84908333808
Name7,2-s2.0-84925879816
Name8,2-s2.0-84940447040,2-s2.0-84949534001
Name9,2-s2.0-84899915556,2-s2.0-84922392381,2-s2.0-84905079505,2-s2.0-84940931972,2-s2.0-84893682063,2-s2.0-84954285577,2-s2.0-84934934228,2-s2.0-84926624187
Name10,2-s2.0-84907065810

一个观察:你说Name5会有很多边缘,但它的属性是唯一的。此外,当我使用您的数据运行我的代码时,结果表明所有属性都是唯一的,因此图中没有边缘。

我调整了你的数据,以便我只使用每个属性的前12个字符(我使用行new_attributes = [x[:12] for x in new_attributes]执行此操作)。这样我就得到了一些匹配的属性。

现在代码:

import networkx as nx
import csv

G = nx.Graph()

with open('data.csv') as csvfile:
        csv_reader = csv.reader(csvfile, delimiter=',')
        for row in csv_reader:

            new_node = row[0]  # first element in row
            new_attributes = row[1:]  # whole row except the first element
            new_attributes = [x[:12] for x in new_attributes]  # remove this for your data!
            # add the node and its attributes to the graph
            G.add_node(new_node, my_attributes=new_attributes)  # attributes are stored as a list

            # add edges based on existing nodes
            for node, attrs in G.nodes(data=True):
                # skip node we just added
                if node != new_node:
                    for attr in attrs['my_attributes']:
                        # check if any of the attributes for `node` are also in the `new_attributes` list
                        if attr in new_attributes:
                            G.add_edge(node, new_node)

for edge in G.edges():
    print('EDGE:', edge, '| COMMON ATTRIBUTES:', set(G.node[edge[0]]['my_attributes']) & set(G.node[edge[1]]['my_attributes']))

对于每个csv行,我将一个节点(及其属性)添加到图形中,并根据图形中的当前节点(及其属性)添加边缘。 请注意,节点属性存储在列表中,可以使用my_attributes键进行访问。 最后,我还使用特定边缘中节点的匹配属性打印边缘(我使用set&来获取两个属性列表的交集。)

推文数据的输出:

EDGE: ('Name5', 'Name9') | COMMON ATTRIBUTES: {'2-s2.0-84934'}
EDGE: ('Name5', 'Name8') | COMMON ATTRIBUTES: {'2-s2.0-84949'}
EDGE: ('Name8', 'Name9') | COMMON ATTRIBUTES: {'2-s2.0-84940'}
EDGE: ('Name1', 'Name9') | COMMON ATTRIBUTES: {'2-s2.0-84905'}

最后要注意的是:如果您需要在两个节点之间有多条边,请使用MultiGraph