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.
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}]}
`// 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();
});
`
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.
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}]}
`// 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();
});
`