Search code examples
python-3.5networkxdictionary-comprehension

NetworkX errors while adding nodes: "unhashable type: 'dict'" and "ValueError: too many values to unpack (expected 2)"


While running the below NetworkX python 3.5 code (within Jupyter) I get an error that I don't really understand. Any help is greatly appreciated.

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]

And this is where it fails:

## GRAPH construction - adding nodes

for ng1 in list_of_nodegroups1:
    testgraph.add_nodes_from(ng1)

I get this error:

---------------------------------------------------------------------------
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)

Referring to (as I understand it) 2 things:

  • "unhashable type: 'dict'"
  • "ValueError: too many values to unpack (expected 2)"

I am trying to figure out how exactly this could be solved, whether within this code or elsewhere, and any help is much appreciated!

EDIT:

My objective is to have a graph consisting of 4 types of 'children-nodes' being a,b,c,d and 1 type of 'mother-nodes' being E, like this:

[ ('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} ),
]

Solution

  • Documentation for Graph.add_nodes_from(nodes_for_adding, **attr): nodes_for_adding (iterable container) – A container of nodes (list, dict, set, etc.). OR A container of (node, attribute dict) tuples. Node attributes are updated using the attribute dict.

    Each element in your list E is a tuple containing one node and 4 dicts, while add_nodes_from only accepts a single dict. Those 4 dicts should be merged into a single dict: {'a': i, 'b': j, 'c': k, 'd': l}.

    Also, the list E has 625 × 5⁴ = 390625 elements. Is this your intention, or you are trying to enumerate the node? If you want to enumerate, it does not work as you expected. Instead, use

    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)]