Ошибки NetworkX при добавлении узлов: нехэшируемый тип: 'dict' и ValueError: слишком много значений для распаковки (ожидается 2)

При запуске приведенного ниже кода NetworkX python 3.5 (в Jupyter) я получаю сообщение об ошибке, которое я не совсем понимаю. Любая помощь приветствуется.

import pandas as pd
import networkx as nx
import numpy as np
import matplotlib.pyplot as plt
import os, warnings     
warnings.filterwarnings('ignore')
%matplotlib inline
%config InlineBackend.figure_format = 'retina'


## NODES

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

E = [ (  'E_%d' % h, {'a': i}, {'b': j}, {'c': k}, {'d': l} )
        for h in range(1,626) for i in range(0,5) 
        for j in range(0,5) for k in range(0,5) 
        for l in range(0,5) ]

## GRAPH initialization

testgraph = nx.Graph()
list_of_nodegroups = [a, b, c , d, E]

И вот где это не удается:

## GRAPH construction - adding nodes

for ng1 in list_of_nodegroups1:
    testgraph.add_nodes_from(ng1)

Я получаю такую ​​ошибку:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/usr/local/lib/python3.5/dist-packages/networkx/classes/graph.py in add_nodes_from(self, nodes_for_adding, **attr)
    535             try:
--> 536                 if n not in self._node:
    537                     self._adj[n] = self.adjlist_inner_dict_factory()

TypeError: unhashable type: 'dict'

During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
<ipython-input-10-718f064c86a3> in <module>()
      1 for ng1 in list_of_nodegroups:
----> 2     testgraph.add_nodes_from(ng1)

/usr/local/lib/python3.5/dist-packages/networkx/classes/graph.py in add_nodes_from(self, nodes_for_adding, **attr)
    540                     self._node[n].update(attr)
    541             except TypeError:
--> 542                 nn, ndict = n
    543                 if nn not in self._node:
    544                     self._adj[nn] = self.adjlist_inner_dict_factory()

    ValueError: too many values to unpack (expected 2)

Ссылаясь на (насколько я понимаю) 2 вещи:

  • "нехешируемый тип: 'dict'"
  • «ValueError: слишком много значений для распаковки (ожидается 2)»

Я пытаюсь выяснить, как именно это можно решить, будь то в этом коде или где-то еще, и любая помощь очень ценится!

РЕДАКТИРОВАТЬ:

Моя цель состоит в том, чтобы иметь граф, состоящий из 4 типов «дочерних узлов», являющихся a, b, c, d, и 1 тип «материнских узлов», являющихся E, например:

[ ('E1', {'a0': 0, 'b0': 0, 'c0': 0, 'd0': 0} ),
  ('E2', {'a1': 1, 'b0': 0, 'c0': 0, 'd0': 0} ),
  ('E3', {'a1': 1, 'b1': 1, 'c0': 0, 'd0': 0} ),
   ...
  ('E625', {'a5': 5, 'b5': 5, 'c5': 5, 'd5': 5} ),
]

person nick88    schedule 11.04.2018    source источник


Ответы (1)


Документация для Graph.add_nodes_from(nodes_for_adding, **attr): nodes_for_adding ( повторяющийся контейнер) - контейнер узлов (список, словарь, набор и т. д.). ИЛИ Контейнер кортежей (узел, атрибут dict). Атрибуты узла обновляются с помощью атрибута dict.

Каждый элемент в вашем списке E представляет собой кортеж, содержащий один узел и 4 словаря, в то время как add_nodes_from принимает только один словарь. Эти 4 словаря нужно объединить в один: {'a': i, 'b': j, 'c': k, 'd': l}.

Кроме того, список E содержит 625 × 5⁴ = 390625 элементов. Это ваше намерение или вы пытаетесь перечислить узел? Если вы хотите перечислить, это не сработает так, как вы ожидали. Вместо этого используйте

from itertools import product

E = [('E_%d' % h, {'a': i, 'b': j, 'c': k, 'd': l})
     for h, (i, j, k, l) in enumerate(product(range(5), repeat=4), start=1)]
person ducminh    schedule 11.04.2018
comment
Спасибо @ducminh. Вы правы насчет того, что dicts должен быть одним (а не 4 отдельными, я упустил это из виду. Моя единственная цель - иметь 4 подтипа узлов, каждый с n вариациями (в этом примере 5). И 5-й 'mother' тип, в котором хранятся все возможные комбинации между ними: 5 ^ 4 625. Но я, возможно, заметил это неправильно. - person nick88; 11.04.2018
comment
Если вы используете for h in ... for i in ... таким образом, он создаст список из 390625 элементов, но будет добавлено только 625 узлов. Например, будет два кортежа ('E1', {...}) и ('E1', {...}), и первый узел, созданный первым кортежом, будет перезаписан вторым кортежем. Вы можете попробовать с меньшими значениями, чтобы увидеть эффект. - person ducminh; 11.04.2018