【问题标题】:Represent relations between entities using python3使用python3表示实体之间的关系
【发布时间】:2018-08-07 19:57:50
【问题描述】:

我想使用 Python3 的 networkx 库来表示一系列数据,但我不知道如何解决这个问题。

基本上我在两个entities 之间有一个relation,它位于一个名为nations.csv 的csv 文件中。它看起来像这样:

China, Economicaid, Egypt
China, Economicaid, Indonesia
USSR, Economicaid, Cuba 
USSR, Economicaid, India
USSR, Economicaid, Poland
UK, Economicaid, India 
UK, Economicaid, Jordan
USA, Economicaid, Brazil

了解第一行是与第二行之间的第三行(实体 2)相关的实体之一:

我已经解析了 csv 文件,以便将每一行存储在字典中,如下所示:

d = {}
d['entity1'] = []
d['relation'] = []
d['entity2'] = []

dictReader = csv.DictReader(open('nations.csv', 'rt'), fieldnames = 
['entity1', 'relation', 'entity2'], delimiter = ',', quotechar = '"')

for row in dictReader:
    for key in row:
        d[key].append(row[key])

我设法做的是使用函数add_node() 绘制节点,如下例所示:

import csv
import networkx as nx
import matplotlib.pyplot as plt


d = {}
d['entity1'] = []
d['relation'] = []
d['entity2'] = []

dictReader = csv.DictReader(open('nations.csv', 'rt'), fieldnames = ['entity1', 'relation', 'entity2'], delimiter = ',', quotechar = '"')

for row in dictReader:
    for key in row:
        d[key].append(row[key])

print()

for i in range (1, len(d['entity1'])):
    r.append(d['entity1'][i])

for k in range (1, len(d['entity2'])):
    o.append(d['entity2'][k])


G=nx.Graph()

for j in range(len(r)):
    G.add_node(r[j])
    G.add_node(o[j])

nx.draw_networkx(G, with_labels = True, node_size = 500)

plt.show()

但是当我想表示节点之间的边时,问题就来了,因为它不仅是边本身,它还有自己的带有含义的标签。

【问题讨论】:

  • 边缘的“含义”是什么?您可以将属性添加到边缘on construction 或to existing edges。一个文本标签就够了吗?
  • @Bonlenfum 边缘表示每个关系,因此它必须根据关系的类型有自己的标签。在我的nations.csv 示例中,我只放置了一种类型的关系,但它们有很多。
  • 如果同一对节点之间可能存在多种类型的关系,您应该查看多重图。但是鉴于下面接受的答案,我想您的意思是不同节点对之间的关​​系不同,在这种情况下,边缘属性可以解决它。

标签: python python-3.x matplotlib graph networkx


【解决方案1】:

基本上,标志with_labels 应该真正称为with_node_labels,因为它只触发节点标签的绘制。因此,您需要在绘制图形 (networkx.draw`) 后手动添加边缘标签 (networkx.draw_networkx_edge_labels),并且您需要 1) 在同一轴上绘图,以及 2) 对两个绘图使用相同的图形布局。

import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
import csv

# load data
dictReader = csv.DictReader(open('nations.csv', 'rt'), fieldnames = ['entity1', 'relation', 'entity2'], delimiter = ',', quotechar = '"')

# create a more amenable data structure
edge_to_label = {(d['entity1'], d['entity2']) : d['relation'] for d in dictReader}

# create graph
G = nx.from_edgelist(edge_to_label.keys())

# precompute layout (default layout used here)
layout = nx.layout.fruchterman_reingold_layout(G)

# create figure so we plot the graph and labels on the same plot
fig, ax = plt.subplots(1,1)

# draw graph
nx.draw(G, pos=layout, ax=ax, with_labels=True)

# draw labels using the same, pre-computed graph layout
nx.draw_networkx_edge_labels(G, pos=layout, edge_labels=edge_to_label, ax=ax)

plt.show()

【讨论】:

  • 有没有办法调整代码中的查看条件,使其看起来尽可能最好?因为线条很少,所以图表很小,但我需要放置更多实体。
  • 如果不是直接相关的后续问题,您真的应该打开另一个问题。您的后续行动是关于具有许多节点的网络的布局选项,这绝对是不相关的。话虽如此,我建议您开始阅读 networkx 代码文档并尝试使用这些选项。您应该特别熟悉节点放置的不同布局选项;也许有一个可以满足您的需求。如果无法访问您的数据,没有人能够给您一个体面的答案(除非是偶然)。
  • 即使可以访问您的数据,看起来“可能的最佳方式”也只是个人喜好问题,而不是任何客观、可衡量的标准。
  • 对不起。这个答案没有将标签的信息添加到图形 G 中,而只是将其绘制出来对吗?但是在networkx中关系可以有属性,为什么不先把这些信息加入到图G中呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-13
  • 2014-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多