Print networkx DiGraph to Nested JSON format

Question:

I have a networkx DiGraph.

>> G = nx.DiGraph()
>> G.add_edges_from(product([0],[1,2])) # product is itertools.product 
>> G.add_edges_from(product([1],[3,4])) 

The graph looks like this inside:

>> G.adj  
 {0: {1: {}, 2: {}},  
  1: {3: {}, 4: {}},  
  2: {},  
  3: {},  
  4: {}} 

I would like this to be printed to a json format like the following:

{   
    name: 0,
    children: [ 
        {
            name: 1,
            children: [
                {
                    name: 3,
                    children: [] 
                }, 
                {
                    name: 4,
                    children: []
                }
                ]
        }, 
        {
            name: 2,
            children:[]
        }
    ]
} 

(The reason being, I am trying to write it in a format that this D3 visualization takes in. https://gist.github.com/mbostock/4063550)

I am not sure how to go about this. Any help much appreciated.

thanks.

Asked By: jason

||

Answers:

You can use json_graph.tree_data() to output the data in a nested format.

From the documentation

from networkx.readwrite import json_graph
import networkx as nx
import json
G = nx.DiGraph([(1,2)])
data = json_graph.tree_data(G,root=1)
s = json.dumps(data)

Which gives {"id": 1, "children": [{"id": 2}]}

Answered By: Christopher Hackett
`// Set up the D3.js canvas and force layout
const svg = d3.select("svg");
const width = +svg.attr("width");
const height = +svg.attr("height");
const simulation = d3.forceSimulation()
  .force("link", d3.forceLink().id(d => d.id))
  .force("charge", d3.forceManyBody())
  .force("center", d3.forceCenter(width / 2, height / 2));

// Load the data for the graph (empty initially)
let nodes = [];
let links = [];

// Define the drag behavior for the nodes
const drag = d3.drag()
  .on("start", dragStart)
  .on("drag", dragging)
  .on("end", dragEnd);

function dragStart(event, d) {
  if (!event.active) simulation.alphaTarget(0.3).restart();
  d.fx = d.x;
  d.fy = d.y;
}

function dragging(event, d) {
  d.fx = event.x;
  d.fy = event.y;
}

function dragEnd(event, d) {
  if (!event.active) simulation.alphaTarget(0);
  d.fx = null;
  d.fy = null;
}

// Define the update function for the graph
function update() {
  // Create the link and node elements
  const link = svg.selectAll(".link")
    .data(links)
    .join("line")
      .attr("class", "link");
  const node = svg.selectAll(".node")
    .data(nodes)
    .join("circle")
      .attr("class", "node")
      .attr("r", 10)
      .call(drag);

  // Update the positions of the link and node elements
  link.attr("x1", d => d.source.x)
      .attr("y1", d => d.source.y)
      .attr("x2", d => d.target.x)
      .attr("y2", d => d.target.y);
  node.attr("cx", d => d.x)
      .attr("cy", d => d.y);

  // Update the simulation with the new node and link data
  simulation.nodes(nodes).on("tick", ticked);
  simulation.force("link").links(links);

  function ticked() {
    link.attr("x1", d => d.source.x)
        .attr("y1", d => d.source.y)
        .attr("x2", d => d.target.x)
        .attr("y2", d => d.target.y);
    node.attr("cx", d => d.x)
        .attr("cy", d => d.y);
  }
}

// Call the update function initially to render the empty graph
update();

// Define the event listener for adding new nodes
svg.on("click", event => {
  // Add a new node with a unique ID
  const newNode = {id: nodes.length.toString()};
  nodes.push(newNode);

  // Add a new link to any existing node
  if (nodes.length > 1) {
    const source = nodes[nodes.length - 2];
    const target = newNode;
    const newLink = {source, target};
    links.push(newLink);
  }

  // Update the graph display
  update();
});
`
Answered By: Harish R