我尝试使用给定节点和属性的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的任何文档或视频。
答案 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
。