【问题标题】:Having nodes with differing lengths of attributes, add edges if >=1 attribute is the same具有不同属性长度的节点,如果 >=1 属性相同,则添加边
【发布时间】:2018-09-22 05:14:40
【问题描述】:

在 NetworkX 中试图完成以下任务:

  • 在一个图中创建“母节点”和“子节点”,其中子节点只有 1 个属性,而母节点有多个 (4)。
  • 如果至少一个属性(键值对)相同,则在母节点和子节点之间创建边,
  • 仅在母节点和子节点之间创建边:即使两个母节点具有 4 个重叠属性之一,两者之间也不应该有边

到目前为止,我已经完成了第一部分,第二部分 michaelg 非常有帮助,但仍然存在错误。

import networkx as nx
from itertools import product

# Mother-nodes
M = [('E_%d' % h, {'a': i, 'b': j, 'c': k, 'd': l})
 for h, (i, j, k, l) in enumerate(product(range(2), repeat=4), start=1)]

# children-nodes
a = [ (  'a_%d' % i, {'a' : i}) for i in range(0,2)  ]
b = [ (  'b_%d' % i, {'b' : i}) for i in range(0,2)  ]
c = [ (  'c_%d' % i, {'c' : i}) for i in range(0,2)  ]
d = [ (  'd_%d' % i, {'d' : i}) for i in range(0,2)  ]

# graph containing both
M_c = nx.Graph()
M_c.add_nodes_from(M)
ls_children = [a, b, c , d]
for ls_c in ls_children:
    M_c.add_nodes_from(ls_c)

# what it looks like so far
list(M_c.nodes(data=True))[0:20]

[('E_9', {'a': 1, 'b': 0, 'c': 0, 'd': 0}),
 ('d_0', {'d': 0}),
 ('E_10', {'a': 1, 'b': 0, 'c': 0, 'd': 1}),
 ('b_0', {'b': 0}),
 ('E_2', {'a': 0, 'b': 0, 'c': 0, 'd': 1}),
 ('E_1', {'a': 0, 'b': 0, 'c': 0, 'd': 0}),
 ('c_1', {'c': 1}),
 ...
    ] 

然后是生成错误的第二部分:

for start in M_c.nodes(data=True):
    for end in M_c.nodes(data=True):
        for attr in list(start[1].keys()):
            if start[1][attr]:
                if end[1][attr]:
                    if start[1][attr] == end[1][attr]:
                        M_c.add_edge(start[0], end[0] )
    # Adding an else and continue statement does not affect the error, 
    # even adding three of them, for each if statement
    #        else:
    #            continue

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-5-32ae2a6095e5> in <module>()
      3         for attr in list(start[1].keys()):
      4             if start[1][attr]:
----> 5                 if end[1][attr]:
      6                     if start[1][attr] == end[1][attr]:
      7                         M_c.add_edge(start[0], end[0] )

KeyError: 'a'

我可能忽略了一些东西 - 任何建议都非常感谢。

EDIT-1:

按照 ducminh 的建议,我跑了:

for mother_node in M:
    for child_node in chain(a, b, c, d):
        if child_node[1].items() <= mother_node[1].items():
            M_c.add_edge(child_node, mother_node)

返回此错误:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-24f1a24a49e8> in <module>()
      2     for child_node in chain(a, b, c, d):
      3         if child_node[1].items() <= mother_node[1].items():
----> 4             M_c.add_edge(child_node, mother_node)
      5 

/usr/local/lib/python3.5/dist-packages/networkx/classes/graph.py in add_edge(self, u_of_edge, v_of_edge, **attr)
    873         u, v = u_of_edge, v_of_edge
    874         # add nodes
--> 875         if u not in self._node:
    876             self._adj[u] = self.adjlist_inner_dict_factory()
    877             self._node[u] = {}

TypeError: unhashable type: 'dict'

【问题讨论】:

    标签: python python-3.5 networkx dictionary-comprehension


    【解决方案1】:

    验证端节点是否存在属性

    由于对起始节点的属性进行了迭代,所以还需要验证它是否存在于结束节点:

    这是修改后的代码:

    for start in M_c.nodes(data=True):
    for end in M_c.nodes(data=True):
        for attr in list(start[1].keys()):
            # verify that the attribute is in the end node
            if attr in end[1]:
                if start[1][attr] == end[1][attr]:
                    M_c.add_edge(start[0], end[0] )
    

    【讨论】:

      【解决方案2】:

      如果一个节点是母节点,它总是拥有所有4个属性a, b, c, d,而一个子节点只有一个属性。因此,dict start[1] 可能有密钥 attr,而 end[1] 没有。

      为了在母节点和子节点之间正确添加边,我们需要遍历所有可能的对(母节点,子节点),然后检查子节点的属性字典是否是子节点的子字典母节点。

      from itertools import chain
      
      for mother_node in M:
          for child_node in chain(a, b, c, d):
              if child_node[1].items() <= mother_node[1].items():
                  M_c.add_edge(child_node[0], mother_node[0])
      

      【讨论】:

      • 谢谢@ducminh!我尝试了你的代码,但它给了我一个错误“TypeError: unhashable type:'dict'”,我在上面问题的“EDIT-1”部分添加了它。
      • 哦我忘了在add_edge中,我们需要传递节点的标签,而不是标签和属性。我已经修复了我的代码。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多