无法通过 NetworkX 中的属性检索节点
Trouble retrieving nodes by attributes in NetworkX
我正在使用 NetworkX 开发代码,其中我有一个类似于以下的多部分图:
每个节点都有以下属性:
- 层:指节点所在的图的列
- 标签:对于每一列,我为每个节点分配一个标签
- 轨迹:是节点之间的关系。如果一个节点与另一个节点相关,则这些节点可能被标记为不同但将共享相同的轨迹。
在上图中,每个节点标签被描述为 'label.layer'(在这种情况下,我们可以看到更大图的子集,因此层数从 451 开始,而不是从 0 开始)。
我想得到的是这个图中的独立字典,这些字典应该只包含属于同一轨迹的节点,即所有彼此相邻的节点。到目前为止,我关注了这些帖子,我的解决方案是:
Select nodes and edges form networkx graph with attributes
for i in range(trajectory):
sel_nodes = dict((node, attribute['trajectory']) for node, attribute in G.nodes().items() if attribute['trajectory'] == i)
print(sel_nodes)
这应该 return 每个 'row' 节点的字典,但是输出是以下字典:
{'0.451': 0, '0.452': 0, '0.453': 0, '0.454': 0, '0.455': 0, '0.456': 0, '0.457': 0, '0.458': 0, '0.459': 0, '0.460': 0}
{'1.451': 1, '1.452': 1, '1.453': 1, '1.454': 1, '1.455': 1, '1.456': 1, '1.457': 1, '1.458': 1, '1.459': 1, '1.460': 1}
{'2.451': 2, '3.452': 2, '3.453': 2, '3.454': 2, '3.455': 2, '3.456': 2, '3.457': 2, '3.458': 2, '3.459': 2, '4.460': 2}
{'3.451': 3, '2.452': 3, '2.453': 3, '2.454': 3, '2.455': 3, '2.456': 3, '2.457': 3, '2.458': 3, '2.459': 3, '3.460': 3}
{'4.451': 4, '4.452': 4, '4.453': 4, '4.454': 4, '4.455': 4, '4.456': 4, '4.457': 4, '4.458': 4, '4.459': 4, '5.460': 4}
{'5.451': 5, '5.452': 5, '5.453': 5, '5.454': 5, '5.455': 5, '5.456': 5, '5.457': 5, '5.458': 5, '5.459': 5, '6.460': 5}
{'6.451': 6, '6.452': 6, '6.453': 6, '6.454': 6, '6.455': 6, '6.456': 6, '6.457': 6, '6.458': 6, '6.459': 6, '7.460': 6}
{'7.451': 7, '7.452': 7, '7.453': 7, '7.454': 7, '7.455': 7, '7.456': 7, '7.457': 7, '7.458': 7, '7.459': 7, '8.460': 7}
{'8.451': 8, '8.452': 8, '8.453': 8, '8.454': 8, '8.455': 8, '8.456': 8, '8.457': 8, '8.458': 8, '8.459': 8, '9.460': 8}
{}
{}
最后两个空字典应该分别包含下行节点和图形最后一列的孤独节点,但事实并非如此,我只能检索到的节点以某种方式连接到第一列。
有什么方法可以解决这个问题吗?
编辑:为了缩小问题的范围,我认为问题出在我使用的字典理解上,因为我已经通过以下方式检查了属性轨迹是否具有分配给它的值:
print(G.nodes['9.455']['trajectory'])
输出给了我轨迹 9,这与我期望的轨迹一致。
我觉得这里的字典列表是错误的数据结构。看起来你真的在寻找一个数据结构,它告诉你,给定一个轨迹 i
,哪些节点属于这个轨迹?集合字典或集合列表似乎更合适。
以下是如何在一个小示例图上构建这样一个列表,其中顶部轨迹是一个孤立的节点,底部的两个轨迹相互交叉:
>>> import networkx as nx
>>> G = nx.Graph()
>>> G.add_nodes_from([(0.3, {"trajectory": 0}), (1.1, {"trajectory": 1}), (2.2, {"trajectory": 1}), (2.3, {"trajectory": 1}), (2.1, {"trajectory": 2}), (1.2, {"trajectory": 2}), (1.3, {"trajectory": 2})])
>>> from collections import defaultdict
>>> d = defaultdict(set)
>>> for node, attrs in G.nodes().items():
... d[attrs["trajectory"]].add(node)
...
>>> d
defaultdict(<class 'set'>, {0: {0.3}, 1: {1.1, 2.2, 2.3}, 2: {1.2, 2.1, 1.3}})
如果你真的想要上面描述的字典列表,你可以从这里轻松构建它:
>>> for trajectory, nodes in d.items():
... print({node: trajectory for node in nodes})
...
{0.3: 0}
{1.1: 1, 2.2: 1, 2.3: 1}
{1.2: 2, 2.1: 2, 1.3: 2}
如果你想要每个轨迹的有序列表而不是集合,你可以对小数点后的名称部分进行排序:
>>> d = {k: sorted(nodes, key=lambda x: str(x)[2:]) for k, nodes in d.items()}
>>> d
{0: [0.3], 1: [1.1, 2.2, 2.3], 2: [2.1, 1.2, 1.3]}
我正在使用 NetworkX 开发代码,其中我有一个类似于以下的多部分图:
每个节点都有以下属性:
- 层:指节点所在的图的列
- 标签:对于每一列,我为每个节点分配一个标签
- 轨迹:是节点之间的关系。如果一个节点与另一个节点相关,则这些节点可能被标记为不同但将共享相同的轨迹。
在上图中,每个节点标签被描述为 'label.layer'(在这种情况下,我们可以看到更大图的子集,因此层数从 451 开始,而不是从 0 开始)。
我想得到的是这个图中的独立字典,这些字典应该只包含属于同一轨迹的节点,即所有彼此相邻的节点。到目前为止,我关注了这些帖子,我的解决方案是:
Select nodes and edges form networkx graph with attributes
for i in range(trajectory):
sel_nodes = dict((node, attribute['trajectory']) for node, attribute in G.nodes().items() if attribute['trajectory'] == i)
print(sel_nodes)
这应该 return 每个 'row' 节点的字典,但是输出是以下字典:
{'0.451': 0, '0.452': 0, '0.453': 0, '0.454': 0, '0.455': 0, '0.456': 0, '0.457': 0, '0.458': 0, '0.459': 0, '0.460': 0}
{'1.451': 1, '1.452': 1, '1.453': 1, '1.454': 1, '1.455': 1, '1.456': 1, '1.457': 1, '1.458': 1, '1.459': 1, '1.460': 1}
{'2.451': 2, '3.452': 2, '3.453': 2, '3.454': 2, '3.455': 2, '3.456': 2, '3.457': 2, '3.458': 2, '3.459': 2, '4.460': 2}
{'3.451': 3, '2.452': 3, '2.453': 3, '2.454': 3, '2.455': 3, '2.456': 3, '2.457': 3, '2.458': 3, '2.459': 3, '3.460': 3}
{'4.451': 4, '4.452': 4, '4.453': 4, '4.454': 4, '4.455': 4, '4.456': 4, '4.457': 4, '4.458': 4, '4.459': 4, '5.460': 4}
{'5.451': 5, '5.452': 5, '5.453': 5, '5.454': 5, '5.455': 5, '5.456': 5, '5.457': 5, '5.458': 5, '5.459': 5, '6.460': 5}
{'6.451': 6, '6.452': 6, '6.453': 6, '6.454': 6, '6.455': 6, '6.456': 6, '6.457': 6, '6.458': 6, '6.459': 6, '7.460': 6}
{'7.451': 7, '7.452': 7, '7.453': 7, '7.454': 7, '7.455': 7, '7.456': 7, '7.457': 7, '7.458': 7, '7.459': 7, '8.460': 7}
{'8.451': 8, '8.452': 8, '8.453': 8, '8.454': 8, '8.455': 8, '8.456': 8, '8.457': 8, '8.458': 8, '8.459': 8, '9.460': 8}
{}
{}
最后两个空字典应该分别包含下行节点和图形最后一列的孤独节点,但事实并非如此,我只能检索到的节点以某种方式连接到第一列。
有什么方法可以解决这个问题吗?
编辑:为了缩小问题的范围,我认为问题出在我使用的字典理解上,因为我已经通过以下方式检查了属性轨迹是否具有分配给它的值:
print(G.nodes['9.455']['trajectory'])
输出给了我轨迹 9,这与我期望的轨迹一致。
我觉得这里的字典列表是错误的数据结构。看起来你真的在寻找一个数据结构,它告诉你,给定一个轨迹 i
,哪些节点属于这个轨迹?集合字典或集合列表似乎更合适。
以下是如何在一个小示例图上构建这样一个列表,其中顶部轨迹是一个孤立的节点,底部的两个轨迹相互交叉:
>>> import networkx as nx
>>> G = nx.Graph()
>>> G.add_nodes_from([(0.3, {"trajectory": 0}), (1.1, {"trajectory": 1}), (2.2, {"trajectory": 1}), (2.3, {"trajectory": 1}), (2.1, {"trajectory": 2}), (1.2, {"trajectory": 2}), (1.3, {"trajectory": 2})])
>>> from collections import defaultdict
>>> d = defaultdict(set)
>>> for node, attrs in G.nodes().items():
... d[attrs["trajectory"]].add(node)
...
>>> d
defaultdict(<class 'set'>, {0: {0.3}, 1: {1.1, 2.2, 2.3}, 2: {1.2, 2.1, 1.3}})
如果你真的想要上面描述的字典列表,你可以从这里轻松构建它:
>>> for trajectory, nodes in d.items():
... print({node: trajectory for node in nodes})
...
{0.3: 0}
{1.1: 1, 2.2: 1, 2.3: 1}
{1.2: 2, 2.1: 2, 1.3: 2}
如果你想要每个轨迹的有序列表而不是集合,你可以对小数点后的名称部分进行排序:
>>> d = {k: sorted(nodes, key=lambda x: str(x)[2:]) for k, nodes in d.items()}
>>> d
{0: [0.3], 1: [1.1, 2.2, 2.3], 2: [2.1, 1.2, 1.3]}