4

In a directed graph in which the nodes have not only IDs, but also data (a dictionary of attributes), I'd to obtain the DFS tree starting from a given source node, including the data of the child nodes.

I've noticed, however, that the nx.dfs_tree function seems to return a tree without any data:

In [1]: import networkx as nx

In [2]: G = nx.DiGraph()

In [3]: G.add_nodes_from([(0, {'name': 'foo'}), (1, {'name': 'bar'}), (2, {'name
   ...: ': 'baz'})])

In [4]: G.add_edge(0, 1)

In [5]: G.add_edge(1, 2)

In [6]: T = nx.dfs_tree(G, 1)

In [7]: T.nodes[1]
Out[7]: {}

In [8]: T.nodes[2]
Out[8]: {}

In [9]: T.nodes
Out[9]: NodeView((1, 2))

In [10]: G.nodes[1]
Out[10]: {'name': 'bar'}

As seen from the example above, T.nodes[1] is an empty dictionary, whereas G.nodes[1] contains the data dictionary originally passed in.

How can I make it so that T.nodes[1] and other tree nodes contain the same data as the original graph?

Kurt Peek
  • 52,165
  • 91
  • 301
  • 526

2 Answers2

3

I ended up copying over the data from G to T using the add_nodes_from method, which updates existing attributes:

In [31]: T.add_nodes_from((i, G.nodes[i]) for i in T.nodes)

In [32]: T.nodes[1]
Out[32]: {'name': 'bar'}

Any more elegant solutions would be much appreciated.

Kurt Peek
  • 52,165
  • 91
  • 301
  • 526
2

I would suggest using G.subgraph(). Extract all the data from the graph with the nodes returned from the dfs tree, like so G.subgraph(nx.dfs_tree(G, 1).nodes()) This avoids the comprehension list of going through every node individually, and it automatically stores both node data and edge data, while add_nodes_from() only adds the node data of graph G

sprico27
  • 42
  • 4